Архив автора: admin

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

В системном программирования достаточно часто возникает ситуация, когда значительная часть функциональности программы перекладывается на внешние компоненты. Типичный пример — операции с iptables, дисковыми образами и виртуальными машинами. Классически для тестирования такого кода используются массовые моки, отрезающие тестируемый код от всех внешних зависимостей.

При очевидных достоинствах (полная независимость тестов от внешнего мира, скорость исполнения, etc) у моков есть некоторое количество недостатков — самый главный это переход от тестирования того что должно быть сделано к тестирования того как это сделано. Если нужно проверить функцию, которая настраивает проброс порта, то вместо тестирования результата (правильного прохождения пакетов) проверяется, что iptables вызвалась с правильными параметрами.

По итогу юнит тест проверяет не правильность работы кода, а является отражением его структуры. Такой тест помогает обеспечить постоянную проверку на отсутствие AttributeError и ему подобных (python), но на этом его полезность оканчивается. Учитывая желание менеджера и/или заказчика получить заветные X% покрытия ситуация становится совсем идиотской. Несколько последних проектов, в которых я учавствовал были именно такие — тонкая прослойка из python, связывающая вместе БД, REST, xen, iptables и еще горстку linux утилит в небольшой специализированный клауд. По итогу заметная часть UT требует переписывания после каждого рефакторинга, потому как изменилось взаимодействие с внешними компонентами. То что должно поощрять рефакторинг и улучшение кода становится одним из главных его тормозов.

Частично эта ситуация отражает объективный факт — мы не можем позволить юнит-тестам бесконтрольтно модифицировать файловую систему на локальной машине, изменять правила прохождения пакетов или ip маршруты. Дополнительный минус — рабочая машина разработчика не всегда соответствует требованиям к конечному серверу.

Решение совершенно очевидное — использовать для тестов виртуальные машины и проводить тесты на необходимой конфигурации + исключить бОльшую часть моков из тестов.

Итого — что хотелось получить:

  • исполнять отдельные юнит-тесты на виртуальных машинах или группах машин
  • интеграция с nosetests и coverage
  • максимально простое использование
  • высокая скорость — юнит-тесты должны исполняться быстро

Как хотелось это использовать:

Без подсветки синтаксиса

@on_vm('worker-1')
def test_iptables():
    make_iptables_rules()
    check_packages_goes_ok()

@on_vm(‘worker-2’)
def test_something():
make_something()
check_something_works()

 

@on_vm('worker-1')
def test_iptables():
    make_iptables_rules()
    check_packages_goes_ok()

@on_vm(‘worker-2’)
def test_something():
make_something()
check_something_works()

 

Доводить идею до рабочего варианта в рамках внутреннего проекта взялись интерны нашей компанииИгорь Гарагатый и Настя Криштопа.

Для начала было решено реализовать достаточно простой вариант: перед исполнением каждого теста, требующего виртуальную машину, запускалась соответствующая vm, на нее копировался код и тесты, запускались тесты и их результаты тестов возвращались назад на хост машину. Если тест выбросит исключение оно должно передаваться назад на хост и выбрасываться из локального теста — nose не должен замечать разницы между локальным и удаленным исполнением теста.

В итоге были выбраны два варианта — LXC и KVM. LXC позволяет запустить виртуальную машину менее чем за секунду и не требует аппаратной поддержки виртуализации, а KVM это более надежный вариант, позволяющий запускать виртуальные машины любых конфигураций (LXC использует ядро хост системы, поэтому поднять в нем другую версию ядра или другую OS невозможно).

Хотелось иметь в vm файловую систему доступную для записи, но возвращаемую в начальное состояние после окончания теста. Для kvm это естественным образом решается возможностями qcow2, который позволяет сохранять все изменения в отдельный файл, не трогая оригинальный образ. Для LXC же нужна была файловая система с поддержкой снимков и быстрым откатом к ним. После рассмотрения btrfs, LVM+XFS и aufs решили остановиться на первом варианте.

Что в итоге получилось:

  • Пользователь подготавливает образы и конфигурации виртуальных машин, которые будут использоваться для UT
  • Оборачивает отдельные тесты декоратором on_vm с указанием на какой конфигурации его запускать
  • nosetests unitTests
  • profit (итоги тестов и coverage)

Примерная схема работы:

  • Декоратор on_vm создает отдельный процесс, для поднятия ВМ и запускает поток, слушающий результаты на сокете
  • test_executor.py создает с помощью libvirt необходимую конфигурацию vm, предварительно сделав слепок btrfs или подключив qcow2 файл для сохранения изменений (в зависимости от типа виртуальной машины)
  • test_executor.py дожидается окончания запуска vm, копирует туда необходимые файлы и запускает только выбранные тест на исполнение, предварительно выставив переменные окружения
  • on_vm по переменным окружения определяет, что это реальных запуск и исполняет тест
  • при возникновении ошибки она сериализуется и передается на хост
  • итоги теста передаются на хост вместе с результатами покрытия
  • процесс на хосте принимает результаты, гасит vm, откатывает состояние образа и имитирует локальное исполнение теста.

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

Ссылки:
github.com/koder-ua/vm_ut
koder-ua.blogspot.com/2012/01/lxc.html
mirantis.com
github.com/ogirOK
github.com/anakriya
pypi.python.org/pypi/coverage
readthedocs.org/docs/nose/en/latest

Исходники этого и других постов со скриптами лежат тут — github.com/koder-ua. При использовании их, пожалуйста, ссылайтесь на koder-ua.blogspot.com.

Автор: konstantin danilov

Запуск процессов в linux с ограничением ресурсов

Иногда хочется ограничить максимальное количество ресурсов доступных процессу. Последней пинком стали юнит-тесты из текущего проекта — из-за ошибок они несколько раз съели все 8Gb ОЗУ и отправили систему в глубокий своп, откуда она со скрипом доставалась минут 15. Полная виртуализация таких случаях избыточна — нужно что-то по легче. В linux для этого есть cgroups (control groups) — они позволяют поместить процесс (вместе со всеми его потомками) в контейнер, имеющий доступ только к части ресурсов системы. На самом деле cgroups умеют больше, чем просто ограничение ресурсов — тут и счетчики производительности и другая статистика.

cgroups можно манипулировать вручную или с помощью libcgroup. Последний способ значительно удобнее и по нему есть отличная документация от redhat. Она обязательна к прочтению — есть несколько не очевидных моментов (для пользователей ubuntu — в этом дистрибутиве по умолчанию cgroups монтируются в /sys/fs/cgroups).

Читать

картина из гальки

Оригинальные идеи из гальки

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

оригинальные идеи из гальки

оригинальные идеи из гальки

Читать

Технические задачки

1. Что будет выведено в результате исполнения программы? Почему?

 

class A:
     def __init__(self, name):
          self.name = name
     def __del__(self):
          print self.name,

aa = [A(str(i)) for i in range(3)]
for a in aa:
del a

Читать

Как делается бутоньерка своими руками

Как делается бутоньерка своими руками

Тем, у кого скоро свадьба, предлагаем узнать, как делается бутоньерка своими руками, и научиться делать такую красоту.

бутоньерка своими руками

бутоньерка своими руками

Читать

Видео уроки для начинающих пользователей Linux Ubuntu

Видеоуроки для начинающих пользователей Linux.
0. Подготовка к установке Ubuntu 10.04 (130 Мб)
1. Настройка Bios (30,2 Мб)
2. Установка Linux Ubuntu 10.04 (108 Мб)
3. Файловый менеджер в Linux Ubuntu 10.04 (65,6 Мб)
4. Работа с файловой системой в командной строке (14,6 Мб)
5. Установка драйвера видеокарты NVIDIA (117 Мб)
6. Обзор графической среды Gnome (80,6 Мб)
7. Настройка внешнего вида графической среды Gnome (67,7 Мб)
8. Установка программ в Linux Ubuntu 10.04 (94 Мб)
Читать