Архив рубрики: Linux

Новости Ubuntu 12.04 LTS

Завершился саммит разработчиков Ubuntu Linux, на котором были приняты решения, касающиеся подготовки релиза Ubuntu 12.04 LTS и рассмотрены некоторые предложения по дальнейшему развитию проекта. Ниже представлена подборка интересных обсуждений. Читать

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

В системном программирования достаточно часто возникает ситуация, когда значительная часть функциональности программы перекладывается на внешние компоненты. Типичный пример — операции с 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).

Краткий пересказ документации на примере ubuntu/libcgroup.

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

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

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

# apt-get install cgroup-bin

# apt-get install cgroup-bin

После установки в системе появится сервис cgconfig, который автоматически создает иерархию групп и контроллеров по описанию из файла /etc/cgconfig.cfg. После правки файла сервис необходимо перезапустить. Иногда он не может корректно перезапуститься из-за не отмонтированных при останове контроллеров. Лечится это ручным отмонтированием контроллеров:

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

$ sudo service cgconfig restart
[sudo] password for koder:
stop: Job failed while stopping
$ lscgroups
cpuset:/
cpuset:/sysdefault
$ rm -rf /sys/fs/cgroup/cpuset/sysdefault
$ umount /sys/fs/cgroup/cpuset
$ umount /sys/fs/cgroup
# # теперь можно перезапускать

$ sudo service cgconfig restart
[sudo] password for koder:
stop: Job failed while stopping
$ lscgroups
cpuset:/
cpuset:/sysdefault
$ rm -rf /sys/fs/cgroup/cpuset/sysdefault
$ umount /sys/fs/cgroup/cpuset
$ umount /sys/fs/cgroup
# # теперь можно перезапускать

Второй интересный сервис — cgred. Он умеет автоматически распределять процессы по группам в зависимости от правил, описанных в /etc/cgrules.conf. По умолчанию не запущен.

После установки cgroup-bin в /sys/fs/cgroup появится группы из стартового конфига:

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

$ ls /sys/fs/cgroup
cpu cpuacct device s freezer memory

$ ls /sys/fs/cgroup
cpu cpuacct devices freezer memory

К каждой иерархии привязан один контроллер с соответствующим именем. Что-бы поместаить процесс под управление одного из контроллеров нужно выполнить 3 шага:

  • Сделать группу. sudo mkdir /sys/fs/cgroup/memory/test создаст группу test под управлением контроллера memory. В папке /sys/fs/cgroup/memory/test тут же появятся специальные файлы для управления и мониторинга группы.
  • Настроить контроллер. Некоторые контроллеры готовы к работе сразу, а некотрые требуют предварительной настройки. Правила настройки контроллеров не очень очевидны и описаны в документации. Для memory минимально необходимо записать ограничение в файл limit_in_bytes.

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

$ sudo echo 4M > /sys/fs/cgroup/memory/test/limit_in_bytes

$ sudo echo 4M > /sys/fs/cgroup/memory/test/limit_in_bytes

Теперь процессы в группе могут использовать не больше 4M ОЗУ на всех.

  • Перенести процесс в группу — для этого нужно записать его pid в файл /sys/fs/cgroup/memory/test/tasks.

Когда группа станет не нужна ее можно удалить через rm -rf. Что-бы создать подгруппу нужно сделать новую папку в папке группы.

cgroups-bin предлагает чуть более удобный интерфейс для управления группами:

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

# cgcreate -g memory:/test # создать группу tt под управлением контроллера memory

# lscgroup memory:/
memory:///
memory:///test
memory:///sysdefault


# cgset -r memory.limit_in_bytes=4M memory:test # устанавливаем limit
# cgexec -g memory:test python -c "range(10000000000)" # пытаемся сделать всем плохо
Killed

# cgdelete memory:test # удалить группу

# lscgroup memory:/
memory:///
memory:///sysdefault

# cgcreate -g memory:/test # создать группу tt под управлением контроллера memory

# lscgroup memory:/
memory:///
memory:///test
memory:///sysdefault


# cgset -r memory.limit_in_bytes=4M memory:test # устанавливаем limit
# cgexec -g memory:test python -c "range(10000000000)" # пытаемся сделать всем плохо
Killed

# cgdelete memory:test # удалить группу

# lscgroup memory:/
memory:///
memory:///sysdefault

Чтобы не делать это каждый раз руками можно настроить cgred или написать автоматизирующий скрипт; я сделал себе такой:

Показать код

#!/bin/bash
#set -x
USAGE="Usage: `basename $0` [-h] [-m MEM_LIMIT_IN_MEGS] [-c CPUS] [-i IOLIMIT] [-u USER] CMD"

cgroup_mount=/sys/fs/cgroup

GROUP=app_cell_1
while [ true ] ; do

OK=1
for cgroup in `lscgroup | awk -F: '{print $1}' | uniq`; do
if [ -d $cgroup_mount/$cgr oup/$GROUP ] ; then
OK=0
break
fi
done

if (( $OK==1 )) ; then
break
fi

GROUP=app_cell_$RANDOM
done

MEMLIMIT=
CPUS=
USER=
IOLIMIT=

while getopts hm:c:i:u: OPT; do
case "$OPT" in
h)
echo $USAGE
exit 0
;;
c)
CPUS=$OPTARG
echo "CPUS = $CPUS"
;;
i)
IOLIMIT=$OPTARG
;;
m)
MEMLIMIT=$OPTARG
;;
u)
USER=$OPTARG
;;
?)
echo $USAGE >&2
exit 1
;;
esac
done

shift $(($OPTIND - 1))

if [ $# -eq 0 ]; then
echo $USAGE >&2
exit 1
fi

CMD=$@

#cgdelete memory:/$GROUP 2>/dev/null
#cgdelete cpuset:/$GROUP 2>/dev/null
#cgdelete blkio:/$GROUP 2>/dev/null

CGEXEC_OPT=
LIMITS=0

if [ -n "$MEMLIMIT" ] ; then
LIMITS=1
cgcreate -g memory:/$GROUP
cgset -r memory.limit_in_bytes=$MEMLIMIT $GROUP
cgset -r memory.memsw.limit_in_bytes=$MEMLIMIT $GROUP
CGEXEC_OPT="$CGEXEC_OPT -g memory:$GROUP"
fi

if [ -n "$CPUS" ] ; then
LIMITS=1
cgcreate -g cpuset:/$GROUP
cgset -r cpuset.cpus=$CPUS $GROUP
cgset -r cpuset.mems=0 $GROUP
CGEXEC_OPT="$CGEXEC_OPT -g cpuset:$GROUP"
fi

if [ -n "$IOLIMIT" ] ; then
echo "IO limits not supported yet" >&2
fi

if (( $LIMITS==0 )) ; then
echo "At least one limit should be set" >&2
echo $USAGE >&2
exit 1
fi

if [ -e "$USER" ] ; then
cgexec $CGEXEC_OPT $CMD
else
cgexec $CGEXEC_OPT su "$USER" -c "$CMD"
fi

#!/bin/bash
#set -x
USAGE="Usage: `basename $0` [-h] [-m MEM_LIMIT_IN_MEGS] [-c CPUS] [-i IOLIMIT] [-u USER] CMD"

cgroup_mount=/sys/fs/cgroup

GROUP=app_cell_1
while [ true ] ; do

OK=1
for cgroup in `lscgroup | awk -F: '{print $1}' | uniq`; do
if [ -d $cgroup_mount/$cgroup/$GROUP ] ; then
OK=0
break
fi
done

if (( $OK==1 )) ; then
break
fi

GROUP=app_cell_$RANDOM
done

MEMLIMIT=
CPUS=
USER=
IOLIMIT=

while getopts hm:c:i:u: OPT; do
case "$OPT" in
h)
echo $USAGE
exit 0
;;
c)
CPUS=$OPTARG
echo "CPUS = $CPUS"
;;
i)
IOLIMIT=$OPTARG
;;
m)
MEMLIMIT=$OPTARG
;;
u)
USER=$OPTARG
;;
?)
echo $USAGE >&2
exit 1
;;
esac
done

shift $(($OPTIND - 1))

if [ $# -eq 0 ]; then
echo $USAGE >&2
exit 1
fi

CMD=$@

#cgdelete memory:/$GROUP 2>/dev/null
#cgdelete cpuset:/$GROUP 2>/dev/null
#cgdelete blkio:/$GROUP 2>/dev/null

CGEXEC_OPT=
LIMITS=0

if [ -n "$MEMLIMIT" ] ; then
LIMITS=1
cgcreate -g memory:/$GROUP
cgset -r memory.limit_in_bytes=$MEMLIMIT $GROUP
cgset -r memory.memsw.limit_in_bytes=$MEMLIMIT $GROUP
CGEXEC_OPT="$CGEXEC_OPT -g memory:$GROUP"
fi

if [ -n "$CPUS" ] ; then
LIMITS=1
cgcreate -g cpuset:/$GROUP
cgset -r cpuset.cpus=$CPUS $GROUP
cgset -r cpuset.mems=0 $GROUP
CGEXEC_OPT="$CGEXEC_OPT -g cpuset:$GROUP"
fi

if [ -n "$IOLIMIT" ] ; then
echo "IO limits not supported yet" >&2
fi

if (( $LIMITS==0 )) ; then
echo "At least one limit should be set" >&2
echo $USAGE >&2
exit 1
fi

if [ -e "$USER" ] ; then
cgexec $CGEXEC_OPT $CMD
else
cgexec $CGEXEC_OPT su "$USER" -c "$CMD"
fi

Используется так:

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

$ sudo ./incontainer -u koder -m 1G -c 0-1 nosetests
# #nosetests ограничен 1 гигабайтом ОЗУ и только двумя ядрами.

$ sudo ./incontainer -u koder -m 1G -c 0-1 nosetests
# #nosetests ограничен 1 гигабайтом ОЗУ и только двумя ядрами.

Скрипт каждый раз создает новую группу вида app_cell_случайное_число, которые нужно периодически удалять, когда в них не останется ни одного процесса. Например, так:

Показать код

#!/bin/bash
cgroup_mount=/sys/fs/cgroup

for cgroup in `lscgroup | awk -F: '{print $1}' | uniq` ; do
for group in `ls -1d $cgroup_mount/$cgroup/app_cell_* 2>/dev/null` ; do
#group=$cgroup_mount/$cgroup/$_group
if [ -d $group ] ; then
TC=`cat $group/tasks | wc -l`
if (( $TC==0 )) ; then
gname=$cgroup:/`basename $group`
echo "Group $gname is empty - clear it"
cgdelete -r $gname
fi
fi
done
done

#!/bin/bash
cgroup_mount=/sys/fs/cgroup

for cgroup in `lscgroup | awk -F: '{print $1}' | uniq` ; do
for group in `ls -1d $cgroup_mount/$cgroup/app_cell_* 2>/dev/null` ; do
#group=$cgroup_mount/$cgroup/$_group
if [ -d $group ] ; then
TC=`cat $group/tasks | wc -l`
if (( $TC==0 )) ; then
gname=$cgroup:/`basename $group`
echo "Group $gname is empty - clear it"
cgdelete -r $gname
fi
fi
done
done

P.S. Ковыряясь в cgroup наткнулся на очень интересный системный вызов

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

prctl(PR_SET_SECCOMP, 0, 0, 0, 0)

prctl(PR_SET_SECCOMP, 0, 0, 0, 0)

После него текущий процесс не может делать никакие системные вызовы, кроме записи/чтения в уже открытые файлы, _exit и sigreturn. Появился в 2.6.33, вместе с cgroups отличная идея для интерпретации/валидации потенциально опасных данных, например для реализации интерпретаторов, получающих скрипты из не доверенных источников.

Ссылки:
          www.mjmwired.net/kernel/Documentation/cgroups.txt
          libcg.sourceforge.net
          docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Resource_Management_Guide
          www.kernel.org/doc/man-pages/online/pages/man2/prctl.2.html

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

Автор: konstantin danilov

Видео уроки для начинающих пользователей 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 Мб)
Читать

Релиз Google Earth 6.2

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

Релиз Google Earth 6.2 вышел на днях и включает множество различных нововведений. Наиболее важным улучшением стало устранение эффекта «стёганного одеяла», которое было вызвано тем, что фотографии делались при различных погодных условиях. Для устранения этого недостатка был применён новый механизм обработки изображения, результат работы которого можно посмотреть на примере скриншота ниже:

 

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

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
Также ожидаемым изменением стала интеграция Google Earth 6.2 с аккаунтом в Google+, позволяющая обмениваться сделанными скриншотами с пользовательскими кругами.
Установка Google Earth 6.2 в Ubuntu

Для установки Google Earth 6.2 потребуется скачать .deb пакет со страницы проекта, предварительно согласившись с лицензией.
Фикс проблем со шрифтом

Для того чтобы исправить проблему с некорректным отображением шрифта потребуется установить пакет «msttcorefonts».

sudo apt-get install msttcorefonts

Обсудить на форуме

Автор: ГАЗЕНВАГЕН™

Вышел релиз Unity 5.2

Вслед за выходом второй альфа Ubuntu 12.04 Precise Pangolin была представлена новая версия Unity 5.2, которая включает многие из уже рассмотренных характеристик, такие как: подсказку с выводом горячих клавиш, новую домашнюю линзу и переключатель Super+Tab для приложений на панели Unity.

Среди других изменений стоит отметить улучшенную поддержку многомониторных конфигурацией, переключение приложений (Alt-Tab) в пределах одного рабочего стола, отключение масштабирования окон программ на экранах с разрешением выше 1024×600 и доработку линз приложений и музыки.

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

Также был улучшен интерфейс линз, в частности музыкальная линза получила трёхколоночный стиль оформления фильтра.

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

 

Ещё одним изменением стало новое поведение Alt + Tab, который теперь по умолчанию переключает окна ограниченные в пределах только одного рабочего стола. Для возможности работы с программами расположенными на нескольких рабочих столах потребуется снять галочку с опции «Bias alt-gab to prefer windows on the current viewport», как на скриншоте ниже:

Теперь доступен новый режим «push to reveal», который позволяет избавиться от случайного появления панели Unity (например при нажатие кнопки назад в Firefox). Настройка доступна через менеджер CompizConfig Settings Manager.

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
Реализована поддержка вставки скопированного текста в строку поиска Dash c помощью клика средней кнопкой мыши.
Полный список изменения в Unity 5.2 доступен тут: launchpad.net

Пакет с Unity 5.2 доступна для Precise из Unity PPA.

Обсудить на форуме

Автор: ГАЗЕНВАГЕН™