OpenStack Cinder provides an API to attach/detach volume to Nova instances. This is public, but not documented API which is used only by Nova now.  In scope of “Attach/detach volumes without Nova” [1] blueprint we introduce new python-cinderclient extension to provide attach/detach API not only for Nova called python-brick-cinderclient-ext. Before Mitaka release everybody who want to use Cinder volumes not only with Nova instances have to create hardening scripts based on python-cinderclient and os-brick [3] projects to make it done.

Since Mitaka, Cinder opens attach/detach API for any users. It will allow to:

 

  • Attach volume to Ironic instance
  • Attach volume to any virtual/baremetal host which is not provisioned by Nova or Ironic

 

It means, Cinder becomes stand-alone project that could be used outside OpenStack cloud with one limitation: Keystone is still required.

For now, python-brick-cinderclient-ext has only ‘get-connector’ API. Attach/detach features are under development and any feedback are welcome to get implemented in the best way. I hope, it will be implemented and documented as well in scope of Mitaka release cycle.

I will show you how it works in current proof-of-concept code [4]. Anybody is welcome to review and test it:).

To demonstrate this feature I will use virtual Devstack environment with Ironic+Cinder. Here is my local.conf [5].

Current limitations are:

 

  • Ironic instance must have access to API and storage networks (it works on Devstack with a default configuration
  • Users inside instance must have root permissions and be able to install required software

 

Detailed manual how to setup Ironic using Devstack could be found here [6]. Since volumes attach/detach operations require python, open-iscsi, udev and other packages I will use Ubuntu-based image for Ironic instances. You can use Ubuntu cloud image [7] or build your own using ‘disk-image-builder’ tool [8]. I’ve built my Ubuntu image with disk-image-builder:

$  disk-image-create ubuntu vm dhcp-all-interfaces grub2 -o ubuntu-image
$  glance image-create --name ubuntu-image --visibility public \
--disk-format qcow2 \
--container-format bare < ubuntu-image.qcow2

After it we need to run Ironic instance:

#  query the image id of the default cirros image
$  image=$(nova image-list | egrep "ubuntu" | awk '{ print $2 }')
#  create keypair
$  ssh-keygen
$  nova keypair-add default --pub-key ~/.ssh/id_rsa.pub # spawn instance $ prv_net_id=$(neutron net-list | egrep "$PRIVATE_NETWORK_NAME"'[^-]' | awk '{ print $2 }') $ nova boot --flavor baremetal --nic net-id=$prv_net_id --image $image --key-name default testing

Wait until instance is booted and ready [9]:

$  nova list
$ ironic node-list

Now you can connect to the instance using SSH:

$  ssh ubuntu@10.1.0.13

By default, in Devstack both Nova and Ironic instances have access to OpenStack APIs.

To attach volume you need to install required packages inside you instance:

$  sudo apt-get install -y open-iscsi udev python-dev python-pip git

NOTE: if you can't acces Internet inside your instance, try the following command on the DevStack host:

$  sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERAD

Clone and install the latest python-cinderclient (the latests version from PyPi will also work but you'll need to pass --os-volume-api-version explicit):

$  git clone https://github.com/openstack/python-cinderclient.git
$  cd python-cinderclient
$  sudo pip install .

Clone the python-brick-cinderclient-ext and apply the patch:

$  git clone https://github.com/openstack/python-brick-cinderclient-ext.git
$  cd python-brick-cinderclient-ext
$  git fetch https://review.openstack.org/openstack/python-brick-cinderclient-ext refs/changes/44/263744/8 && git checkout FETCH_HEAD
$  sudo pip install .

That’s all! Now, you can attach/detach volumes inside your instance. Because it is still PoC implementation you need few additional steps:

$  PATH=$PATH:/lib/udev
$  export PATH

The steps above is needed until python-brick-cinderclient-ext will use oslo.rootwrap or privsep libraries.

Verify, that python-brick-cinderclient-ext works well [10] (you need to setup your own credentiala and auth_url):

$  cat << EOF >> ~/openrc
 #!/usr/bin/env bash
export OS_AUTH_URL="http://10.12.0.26:5000/v2.0"
export OS_IDENTITY_API_VERSION="2.0"
export OS_NO_CACHE="1"
export OS_PASSWORD="password"
export OS_REGION_NAME="RegionOne"
export OS_TENANT_NAME="admin"
export OS_USERNAME="admin"
export OS_VOLUME_API_VERSION="2"
 EOF
$  source ~/openrc
$  sudo -E cinder get-connector

You should get something this: [11].

Finally, create and attach volume to your Ironic instance:

$ cinder create 1
$ sudo -E PATH=$PATH cinder local-attach 0a946c67-2d5c-4413-b8ec-350240e967d2

You should get something like: [12]

Now you can verify that volume is attached via iSCSI protocol [13]:

$  sudo iscsiadm -m session
$  ls -al /dev/disk/by-path/ip-192.168.122.32:3260-iscsi-iqn.2010-10.org.openstack:volume-625e9acc-d5d8-4e7b-84c6-3b55ed98e3f3-lun-1

Detach is also easy:

$  sudo -E PATH=$PATH cinder local-detach 0a946c67-2d5c-4413-b8ec-350240e967d2

That’s all! You’ve got attached your Cinder volume to an Ironic instance without Nova! You can do the same steps to attach volumes inside Nova instance or your desktop. It will work too. I will show you a demo with Nova instance and cloud config scrips in the next post.

 

[1] https://github.com/openstack/cinder-specs/blob/master/specs/mitaka/use-cinder-without-nova.rst
[2] https://github.com/openstack/python-brick-cinderclient-ext
[3] https://github.com/openstack/os-brick
[4] https://review.openstack.org/263744
[5] https://gist.github.com/e0ne/2579921aba839322decc
[6] http://docs.openstack.org/developer/ironic/dev/dev-quickstart.html#deploying-ironic-with-devstack
[7] https://cloud-images.ubuntu.com/
[8] http://docs.openstack.org/developer/ironic/deploy/install-guide.html#image-requirements
[9] http://paste.openstack.org/show/483734/
[11] http://paste.openstack.org/show/483742/
[12] http://paste.openstack.org/show/483743/


Other useful links:

Didn't google "how to run horizon integration tests" unswer in 10 seconds. Making note how to do it.

My development environment usually looks like: macbook + VM with Ubuntu Server or CentOS without GUI. I try to run all tests inside VMs. In case of Selenium tests, I need some preparation for it:

  1. $ sudo apt-get install firefox
    this command will install FireFox. Selenium has WebDriver for it out of the box
  2. $ sudo apt-get install xvfb
    install Virtual Frame Buffer for X Server (https://en.wikipedia.org/wiki/Xvfb)
  3. Run tests:
    • Simple way for OpenStack Horizon:
      ./run_tests.sh --integration --selenium-headless
    • Hard way for any project:
      • Start xvfb:
        $ sudo Xvfb :10 -ac
      • Start headless FireFox:
        DISPLAY=:10 firefox
      • run tests
Useful links:

It’s my first try to blog in English. Feel free to comment for any typo, grammar errors, etc.

There are nothing new, nothing innovative below. There are just a step-by-step guide to not forget and to not google each time when I need it.

Usually, on my dev environment, I’ve got KVM instances with disk images in QCOW format. So time to time I need to extend my virtual disks to get more free space.

  1. Shutdown VM:
    • `sudo shutdown -p now` inside VM
    • `sudo virsh shutdown <vm_name>` on my host
  2. Find QCOW file to change it:
    Be default, it’s located at `/var/lib/libvirt/images`
    `virsh dumpxml dsvm1 | grep file`
    Find something like:
    <disk type='file' device='disk'>
    <source file='/var/lib/libvirt/images/devstack.img'/>
  3. Create backup of your virtual drive (E.g. `cp /var/lib/libvirt/images/devstack.img /var/lib/libvirt/images/devstack.img.bak`)!!!!
  4. Change QCOW image size: `sudo qemu-img resize /var/lib/libvirt/images/devstack.img +10G`  - this command increases size with 10 GB more
    • If image has snapshots, you need to delete them first:
      sudo qemu-img snapshot -l /var/lib/libvirt/images/devstack.img
      sudo qemu-img snapshot -d <snapshot_id> /var/lib/libvirt/images/devstack.img
  5. Boot VM: `sudo virsh start <vm_name>`
  6. NOTE: I don’t care about disk data in this example. But I have backup (see #3) and can restore all needed data.
    Create new partition table with fdisk. fdisk can’t change partition size, we need to delete and create a new one:
    sudo fdisk /dev/sdb
    ‘d’ - delete partitions(s)
    ‘p’ - create new partition(s)
    ‘w’ - write changes
  7. Mount drive to your VM:
    sudo mount /dev/sdb1 /mnt/data
  8. Create filesystem:
    sudo resize2fs /dev/vda3
  9. In case, if you use something else like parted instead of fdisk, you could just extend filesystem size:
    sudo mkfs.ext3 /dev/sdb1

 


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

Проблема #1 - неправильный пользователь

Не всегда бывает что имя локального пользователя совпадает с удаленным. Ситуация распространенная и описанная всеми, кому не лень. Решение простое - указывем нужного пользователя в переменной env.user:

from fabric.api import *
env.user = 'e0ne'

Проблема #2 - аутентификация

Самый простой способ аутентификации по SSH - имя пользователя и пароль. Самая распространенная проблема - нужно как-то безопасно хранить пароль. А так, как я предпочитаю все скрипты для развертывания хранить в VCS (читать как в git’е), то возникает проблема: нехорошо хранить пароль в репозитории, особенно в открытом на GitHub’е. Решение простое - использование пары public/private RSA ключей. Процесс генерации и настройки (ключевые слова: ssh-keygen, ~/.ssh/known_hosts) описывать сейчас не буду, только то, что касается Jenkins’а.

В моем случае, Jenkins был установлен на Ubuntu server 13.04 командой  “apt-get install jenkins”, поэтому пользователь jenkins в системе создался таким образом, что без подоплнительной настройки под ним не залогинишься. Поэтому использем sudo и генерируем ключи для подключения по SSH, примерно, так:

$ sudo -u jenkins -i ssh-keyget -t rsa

После чего в домашнем каталоге jenkins’а будет лежать пара ключей, публичный из которых нужно положить на наш сервер, на который fabric будет копировать файлы. Достатьid_rsa.pub можно так:

$ sudo -u jenkins -i cat ~/.ssh/id_rsa.pub

И положить этот ключ на сервер, в моем случае в файл /home/e0ne/.ssh/known_hosts.

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

Проблема # 3 - не загружаются файлы

Ошибка тут у меня была совсем непонятной (привет paramiko и протоколу ssh), откатывать настройки или делать это с другим сервером сейчас нет возможности. Да и точно не помню как я пришел к решению. Наверное, после медитации на вывод команды “ls -al”. Задача jenkins job’ы была в том, что нужно было апдейтить простое веб-приложение, а у пользователя, под которым jenkins/fabric подключался к серверу не было прав на запись в нужную директорию. Решилось добавлением пользователя в группу www-data, в которой у меня находится пользователь nginx’а.

Пока все. Эти три проблемы были при попытке “простого копирования” файлов. Дальше будет должно быть интереснее. Или проще. Как повезет:).



Почему-то, информации на тему “что такое network namespace” я практически не нашел, что в очередной раз доказыват: английский - основной язык для ИТ.

Network namespace - это логически отделенный от других стек сетевых протоколов в Linux. Такая себе контейнерная виртуализация для сетевых интервейсов, когда chroot LXC и нужна виртуализация только сетевых интерфейсов. Эмулируется полностью сетевой стек: сетевые интерфейсы, таблица маршрутизации, файрволл и т.д. Так, как это работает на уровне ядра и для определенных процессов, то вполне можно получить рабочую конфигурации, когда на одной машине есть несколько сетевых интерфейсов с одинаковыми IP-адресами и ничто не конфликтует. 

Их поддержка в виде патчей появилась еще в версии 2.6.20 (из коробки в дистрибутивах было замечено мной только начиная с 2.6.32) ядра Linux, а в 3-й ветке стали доступы из коробки. Также для работы с ними необходима утилита iproute2. Полный список дистрибутивов и поддерживаемых ядер можно наяти по ссылке http://code.google.com/p/coreemu/wiki/NamespaceKernels. От себя добавлю, что с Ubuntu 12.04/12.10 проблем не было, а вот на RHEL 6.3 и, основанной на нем, CentOS 6.3 поддержки network namespaces нету на уровне ядра. Сростой способ проверки - посмотреть наличие директории /proc/self/ns/

Основные действия с ними можно выполнять с помощью команды ip netns (ip netns - process network namespace management):

  • ip netns list - посмотреть все network namespaces
  • ip netns add NAME - создать новый network namespace
  • ip netns delete NAME - удалить network namespace
  • ip netns exec NAME cmd - выполнить команду внутри network namespace

При запуске любого процесса с определенным network namespace у него в /proc/ID/ns/ будут данные о данном неймспейсе, что поможет ядру правильно подставить сетевой стек. Также все network namespace можно будет найти в /var/run/netns/ns_name в виде обычных файлов. Пока файловые дескрипторы этих файлов открыты, считается, что network namespacе работает. Если создать файлы /etc/netns/ns_name/{resolv.conf, hosts, ...}, то ip-netns будет подставлять процессам именно эти файлы, а не системные, что очень удобно для отладки и не только.

Чтобы посмотреть в каком network namespace выполняется нужный процесс достаточно посмотреть содержимое директории /proc/proc_id/ns/.

Разные network namespace можно объединять между собой с помощью виртуальных сетевых интерфейсов (veth).

Для того, что бы добавить уже существующий сетевой интерфейс (физический или виртуальный) достаточно выполнить команду:

ip link set eth1 netns samplens

По умолчанию, все сетевые процессы находятся в так называемом initial network namespace, у которого нет имени :). Но все конманды для работы с network namespace кроме имени, в качестве параметров, могут принимать ID процесса, который управляет неймспейсом. Для initial network namespace ID равен 1, что равнозначно ID init процесса. Таким образовом, чтобы обрать интерфейс из неймспейса, его стоит добавить в неймспейс с ID=1:

ip link set eth1 netns 1

 

Дополнительные ссылке по теме:

 

P.S. При виртуализации сетевых интерфейсов не могу не упомянуть про tun/tap устройста (http://www.kernel.org/pub/linux/kernel/people/marcelo/linux-2.4/Documentation/networking/tuntap.txt, http://backreference.org/2010/03/26/tuntap-interface-tutorial/). Что это такое я уже крато писал в одном из предыдущих постов. Сам подход, что они реализовываются через файловые дескрипторы(файлы), существует и по сей день. В Linux - почти все файлы, и сетевые интерфейсы не исключение :)


 

Open vSwitch (http://openvswitch.org/) - это виртуальный свитч, котороый позволяет вам строить виртуальную сеть (SDN) поддерживает различные протоколы для мониторнига и управления (NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag и др). Приставка “open” означает что он является opensource продуктом со всеми вытекающими плюсами и минусами.  На просторах интернета найти документацию по нему и руководства по установки не проблема, если вы знаете английский язык. На русском практически ничего нет:(. Далее я расскажу процесс установки его с исходников на Red Hat Enterprise Linux 6.3 (RHEL) и основанной на базе него бесплатной CentOS 6.3 с ядром 2.6.32-279.el6.x86_64. 

В оффициальной документации Open vSwitch по установке на RHEL достаточно подробно написано как это сделать, но я столкнулся с некоторыми проблемами, о которых следует сказать отдельно.

!!! В примере для простоты делаю все операции от root’а, что категорически рекомендуется делать только в образовательных целях.

 

  1. Устанавливаем нужные пакеты для сборки RPM:
    # yum install -y gcc gcc-c++ make rpm-build rpm-devel rpmdevtools git  make python-devel openssl-devel kernel-devel kernel-debug-devel

  2. Клонируем себе исходный код Open vSwitch:
    # git clone git://openvswitch.org/openvswitch openvswitch-1.9.90

  3. Создаем в домашней директории пользователя, от которого будем создавать RPM нужную структуру папок командой:
    # rpmdev-setuptree
  4. Т.к. на помент написания этого поста последняя версия Open vSwitch была 1.9.90, то создаем соответствующий архив:
    # tar pczf ~/rpmbuild/SOURCES/openvswitch-1.9.90.tar.gz ./openvswitch

  5. Далее для сборки необходима более новая версия утилиты autoconf, чем есть в репозитории. Скачиваем и устанавливаем последнюю:
    # wget http://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.gz
    # ./configure
    # make
    # make install
  6. Переходим в папку с исходниками Open vSwitch и выполняем следующие команды:
    # ./boot.sh
    # ./configure


    Далее можно просто выполнить “make && make install”, но тогда будут проблемы с обновлением/удалением приложения и для следующей установки нужно будет выполнить те же сымые действия.
  7. В папке с Open vSwitch запускаем команду, которая соберет нужную нам rpm:
    # rpmbuild -bb rhel/openvswitch.spec
  8. Аналогичным образом собираем модули для текущей версии ядра:
    # rpmbuild -bb -D "kversion `uname -r`" --target=i686-unknown-linux rhel/openvswitch-kmod-rhel6.spec
  9. Если все прошло успешно (а у меня это было именно так), то устанавливаем полученные rpms:
    # rpm -i kmod-openvswitch-1.9.90-1.el6.x86_64.rpm
    # rpm -i openvswitch-1.9.90-1.x86_64.rpm 

  10. Open vSwitch может заменить собой стандартный модуль bridge и тогда brctl будет работать с Open vSwitch как и с обычными мостами, не подозревая что что-то не так. Для этого отключаем модуль brigde и включаем brcompat, который появился после установки Open vSwitch:
    # rmmod bridge
    # modprode openvswitch
    # modprode brcompat


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

 

 

Ну и последнее, запускаем  Open vSwitch: 

# service openvswitch restart

… и проверяем, что он работает:

# ovs-vsctl show

 


Посмотрим какие сетевые интерфейсы бывают и какие есть на конкретном хоте. Делается это командой “ifconfig” или “ip link show”. У каждого тут будет разный список, в моем случае, команда “ip link show” выводит следующее:

 

Рассмотрим подробнее типы интерфейсов:

lo - local loopback interface, виртуальный интерфейс, который присутствует в ядре, отвечает на адрес 127.0.0.1. Весь пакеты, отправленные на него будут автоматически отправлены обратно на тот же интерфес(адрес), с какого отправили.

ethХ (eth0, eth1 и т.д.) - Ethernet LAN интерфейсы, локальная сеть.

ethX.Y - VLAN интерфейсы

wlanX - беспроводное подключение, Wi-Fi.

vmboxnetX, vmnetX - виртуальные интерфейсы VirtualBox и VmWare соответственно.

brX - bridges, бриджи, мосты. Понятно из названия, более мощный аналог hardware bridges. Соединяет два сегмента ethernet на канальном уровне (2-й уровень модели OSI)

pppX - Point to Point Protocol, PPP VPN соединения, часто подключение 3G-модемом.

tap - полностью виртуальный интеряфейс, который симулирует работу ethernet устройства и работает на каналном уровне, используется для создания мостов.

tun - также полносью виртуальный интерфейс, который работает на сетевом уровне модели OSI, используется для маршрутизации.

tr (Token Ring), sl (Serial Line Internet Protocol) и plip (Parallel Line Internet Protocol) используются гораздо реже (последние лет 5 я их не видел в “живой природе”), поэтому подробно рассказывать о них не вижу смысла.


 


Еще один пост из серии "чтоб не забыть и знать где искать".

По умолчанию, RHEL 6.x и любой другой, основанный на нём (CentOS, Scientific Linux), кроме Fedora, дистрибутив в минимальной установки (в других не проверял) после запуска не поднимает доступные ему сетевые интерфейсы. Для их работоспособности необходимо сделать следующее:

# ifup eht0
# dhclient eth0

Первая команда включает сетевой интерфейс eth0, вторая - запускает DHCP Client. 

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

/etc/sysconfig/network-scripts/ifcfg-eth0

следующим образом:

ONBOOT="yes"
BOOTPROTO="dhcp"

Остальные параметры можно оставить без изменений.