пятница, 16 ноября 2012 г.

Автоматизируем виртуальные машины на Python. Музей граблей.


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

Начал я с того что установил Virtual Box и пробовл рабораться с  vboxapi. Потратил день. Результат: смог создавать виртуальную машину без жесткого диска, как прикрутить жёстский диск так и осталось тайной за семью печатями. Более того, при попытке отправлять нажатия клавиш на VNC консоль виртуальной машины, отправлялся только символ '=' - при этом бесконечно. Собственно, залогиниться так и не удалось.

 Потом я вычитал про libvirt. Из плюсов: она поддерживает различные гипервизоры, такие как KVM, Xen, Virtual Box и другие (см википедию). Оказалось, вполне дружелюбная библиотечка, но и тут не всё гладко: нужно создавать XML конфигурацию виртуальной машины и сети, а для работы с vnc консолью приходится использовать subprocess, вызывая команды 'virsh ...'.
Но с перечисленными недостатками можно смириться, учитывая, что всё остальное просто прекрасно. В процессе моих поисков толкового документа по libvirt мне попался блог (который я и до этого читал, но о другом):
http://koder-ua.blogspot.com/2011/12/libvirt-co-1.html
где очень доходчиво описано "как начать работу с библиотекой". Собственно, это дало мне хорошую возможность начать, после чего я написал свой класс, который умеет создавать и настраивать виртуальную машину, т.е. можно его использовать для полной автоматизации работы со всеми виртуальными машинами.

Код класса, который обеспечит удобную работу с консолью виртуальной машины:
import re, time, pexpect


class kvm_cmd:
    def __init__(self, vm_name):
        self.cmd = None
        self.i = 0
        while self.cmd == None:
            try:
                self.cmd = pexpect.spawn('virsh console ' \
                                            + str(vm_name))
            except:
                pass

    def flush(self, c='.*'):
        for i in range(3):
            try:
                self.cmd.expect(['.*', pexpect.EOF], timeout = 30)
            except:
                pass
            time.sleep(10)

        try:
            self.cmd.expect([c, pexpect.EOF], timeout = 120)
        except:

            pass

    def wait(self, s):
        if s != '':
            try:
                self.cmd.expect('.*' + s + '.*', timeout = 30)
                self.i = 0
            except:
                self.i += 1
                if self.i < 20:
                    self.wait(s)

    def wait_and_accept(self, s):
        try:
            self.wait(s)
        except:
            pass
        self.run('')

    def run(self, s, c=''):
        self.i = 0
        try:
            self.cmd.sendline(s)
        except:
            pass
        self.wait(c)
 Используя этот класс с виртуальными машинами работать просто и весело, например, вот так

console = kvm_cmd('Host1')
console.wait('login')
console.run('user')
console.wait('password')
console.run('secret')

Но иногда одного консольного интерфейса не достаточно, например, если мы не линукс без графической оболочки поднимаем, а свое приложение с графическим интерфейсом, которое надо устанавливать и запускать в системе с графической оболочкой. Здесь одной консолью не обойтись. Что мы можем сделать:
1. Подключаться к X серверу по ssh и таки запускать приложение на своей машине, после чего уже его тестировать.
2. VNC console. Старый проверенный, хотя и не сказать что дедовский ;) способ. К тому же, есть отличная готовая тулза для linux - vncdotool, которую смело можно использовать для таких целей. Умеет тыкать мышкой и посылать нажатия клавиш, делать скриншоты и сверять картинку на экране со скриншотами. Ну или Sikuli, тоже отличный выбор.
3. Какой-то другой, революционный способ, который предложите именно вы.

Эмуляция сетей: dynamips & dynagen & Cisco GNS.


    За неимением реальных дорогостоящих и шумных железок Cisco, мы можем использовать эмулятор, для того чтобы протестировать некоторые функции реальных устройств.
    Ценность подобного программного продукта очень велика, особенно, когда тестовое окружение должно включать в себя множество различных роутеров, и топология сети постоянно изменяется. При этом эмулятор позволяет получать далеко не все функции реальных устройств, съедает много памяти и процессора (образы Cisco IOS загружаются прямо в оперативную память вашей машины). Но оно того стоит, в некоторых случаях.

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

    Но какие есть плюсы для тестировщиков кроме самых очевидных?
Это можно автоматизировать! На Python! ) (dynagen написан на питоне и вы можете непосредственно изменять его, редактируя текстовым редактором файл /urs/bin/dynagen ;) ну или на bash, кому что)
Полезное примечание: мы можем создавать конфигурацию оборудования и топологии сети в графическом редакторе Cisco GNS, сохраняя всю сеть в файл конфигурации, а потом в процессе тестирования подгружать различные конфигурации и получать по запросу различные топологии с уже настроенными устройствами. Этим данная технология вызывает у меня восторг ).

    Смотрим для начала:
1. http://unixadmins.su/index.php?topic=122.0

2. http://adminofsystem.net/2010/08/%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%B5%D0%BC-%D0%BB%D0%B0%D0%B1%D0%BE%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%B8%D1%8E-cisco-%D1%81-%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5%D0%BC-dynamips/

3. http://7200emu.hacki.at/

4. http://unixadmins.su/index.php/topic,905.0.html

Используя эту технологию, мы можем создавать сложные сети, включающие виртуальные машины и роутеры Cisco. При этом роутеры cisco могут взаимодействовать с виртуальными машинами, если создать необходимые бриджи и виртуальные интерфейсы в системе.
Примечание: Для того, чтобы dynamips не съедал весь процессор, нужно использовать значения idlepc для каждого эмулируемого роутера.

Для связи с виртуальными машинами на KVM мы используем виртуальные интерфейсы tap, которые подключаются к бриджам, с которыми, в свою очередь, связаны сетевые интерфейсы виртуальных машин. 

sudo tunctl -t tap1
sudo ifconfig tap1 up
sudo brctl addif virt_br2 tap1

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

import time
from subprocess import Popen, PIPE

 
conf  = '/home/user/configuration_of_cisco_routers.conf'
Popen('killall dynamips', shell=True, stdout=PIPE, stderr=PIPE)
time.sleep(2)
Popen('dynamips -H 7200', shell=True, stdout=PIPE, stderr=PIPE)
time.sleep(5)
Popen('dynagen ' + conf, shell=True, stderr=PIPE, stdout=PIPE)
time.sleep(60)

Этот скрипт перезапускает dynamips и dynagen. (чтобы всё это работало, надо применить хак: sudo vi /usr/bin/dynagen  - строка 1521 - закомментировать несколько строчек кода, чтобы при загрузке конфигурации dynagen не запрашивал подтверждения) Можно и без этого, но тогда придётся через pexpect - кому как нравится.

Далее делаем конфигурацию dynagen:

autostart = True
[localhost:7200]
    workingdir = /tmp
    [[7200]]
        image = /home/user/CiscoIOS/cisco.bin
        ghostios = True
        sparsemem = True
        idlepc = 0x60507884
    [[ETHSW sw1]]
        1 = access 10 NIO_tap:tap1
        2 = access 10
        4 = access 20 NIO_tap:tap2
        5 = access 20
    [[ROUTER R1]]
        console = 2000
        f0/0 = sw1 2
        f0/1 = sw1 5
        model = 7200

вот и всё, теперь осталось только настроить cisco роутеры и сохранить конфигурацию.

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

у всего этого есть графический интерфейс, в котором можно "нарисовать сеть", мониторить состояние узлов, снимать трафик для анализа пакетов и многое другое - Cisco GNS. Есть под винду, линукс и мак.

Другой взгляд

Столько написано, рассказано и показано про вампиров, все знают об этих легендах, сказках и мифах.

И лишь немногим пришла в голову мысль о том, что легенду о кровавых и страшных существах, монстрах, можно превратить в повесть о вечной любви двух бессмертных существ.

На сколько надо иначе чувствовать этот мир, чтобы преодолеть барьер знаний и создать свою идею, пройдя мимо чужих.

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

Это действительно сложно - придумать то, что еще не существует и лишь сможет существовать когда-то в будущем, если тебе удастся выразить своё ощущение того, чего не хватает в этом мире.