Utilizando vagrant-libvirt

Dado que recientemente tuve algunos problemas para utilizar VirtualBox, he decidido utilizar un plugin de vagrant para crear maquinas por medio de libvirt. Tratare de cubrir los puntos esenciales de su instalacion y configuracion en una computadora fisica.

Cabe mencionar que es preferible utilizar virtualizacion por hardware(KVM) que emulacion por software(QEMU) dado sus notables ventajas en rendimiento. Para ello es necesario revisar que se nuestro hardware soporte y tenga habilitada dicha caracteristica, esta validacion es diferente entre distintos fabricantes y se realiza a traves de las configuraciones del BIOS.

Como paso inicial es necesario contar con el servicio de libvirtd correctamente instalado y configurado. Ademas, habilitaremos la capacidad de tener virtualizacion anidada en los modulos del kernel. Esta capacidad permite crear maquinas virtuales dentro de otra maquina virtual sin necesidad de emular las caracteristicas del hardware.

Los comandos necesarios para Fedora 23 son:

$ sudo dnf install -y libvirt
$ sudo systemctl enable libvirtd
$ sudo systemctl start libvirtd
$ sudo rmmod kvm-intel
$ sudo sh -c "echo 'options kvm-intel nested=y' >> /etc/modprobe.d/dist.conf"
$ sudo modprobe kvm-intel
$ sudo usermod -a -G libvirt $USER

Una vez que tenemos el servicio de libvirt ejecutandose, los modulos del kernel configurados y nuestro usuario incluido en el grupo de libvirt, procedemos con la instalacion de Vagrant y sus respectivos plugins

$ sudo dnf install -y https://releases.hashicorp.com/vagrant/1.8.1/vagrant_1.8.1_x86_64.rpm
$ sudo dnf install -y gcc
$ vagrant plugin install vagrant-libvirt

Por ultimo y simplemente para validar que todo funcione correctamente, crearemos un Vagrantfile con un Vagrant box que soporte libvirt como proveedor. En el sitio oficial podremos encontrar una gran variedad de ellos.

Para el arranque de la maquina es necesario ejecutar el comando de vagrant up con el argumento de –provider libvirt o declarar la variable de ambiente VAGRANT_DEFAULT_PROVIDER=libvirt que modifica el valor por defecto del proveedor utilizado por vagrant.

$ vagrant init centos/7
$ vagrant up --provider libvirt

Revision de codigo desde la consola

Como parte de mi proceso de iniciacion como desarrollador de OpenStack y a su vez, tratando de entender mas el codigo fuente de distintos proyectos, he estado realizando algunas revisiones de codigo. Esta actividad principalmente se lleva a cabo mediante el portal web. Pero en busca de metodos alternativos en el que pueda ser mas eficiente este proceso me he aventurado a utilizar gertty.

Gertty es basicamente un cliente de consola para realizar revisiones de codigo provistas por un servidor Gerrit. Fue desarrollado y anunciado por la comunidad de OpenStack en Marzo del 2015 y hoy en dia en su version 1.3.2 es utilizado por algunos desarrolladores.

Dado que es una herramienta nueva para mi, explicare solo algunos pasos para su instalacion y configuracion.

Instalacion

sudo -E pip install gertty

Configuracion

curl https://git.openstack.org/cgit/openstack/gertty/plain/examples/openstack-gertty.yaml -o ~/.gertty.yaml
sed -i "s/CHANGEME/electrocucaracha/g" ~/.gertty.yaml
sed -i "s/sort-by//d" ~/.gertty.yaml
sed -i "s/revers//d" ~/.gertty.yaml
sudo chmod 0600 ~/.gertty.yaml

Cabe mencionar que la contraseña utilizada por el archivo de configuracion es la generada por gerrit. Una vez instalado y configurado es posible utilizarlo desde la terminal:

$ gertty

Nota: Inicialmente tuve problemas para mostrar la lista de proyectos de OpenStack, mi teoria es porque utilizaba una sesion de tmux para iniciar la aplicacion.

Reiniciar uso de memoria virtual en Linux

La memoria virtual es util en aquellas ocasiones en las que la memoria RAM esta siendo completamente utilizada. Esta memoria reside en alguna particion del disco duro y se caracteriza por ser mas lenta en comparacion con la memoria RAM, es por ello que su uso se limita a casos extremos. Por lo general, se recomienda configurar una maquina para que tenga el doble de espacio de memoria virtual que el que se tiene en memoria RAM.

Algunas ocasiones he notado que durante la creacion de maquinas virtuales, vagrant exige grandes cantidades de uso de memoria en periodos breves, lo que trae consigo que algunas paginas inactivas de memoria no logran ser movidas a la memoria RAM una vez establecido el consumo de memoria. Como consecuencia, el sistema utiliza memoria virtual(swap) incluso cuando exista memoria RAM disponible. Para estas ocasiones se puede manualmente reiniciar el uso de la memoria virtual.

Solo el unico requisito que se debe tener para este proceso de limpieza es que se debe tener la cantidad suficiente de memoria RAM que permita mover las paginas inactivas de la memoria virtual.

# swapoff -a  && swapon -a

Esto causara que por un momento el consumo de memoria virtual vaya de 100% a 0%.

Generacion de documentacion para los proyectos de OpenStack

Esta semana estuve trabajando en agregar la capacidad de generacion del diagrama de la Base de Datos utilizada por Neutron. Quiza sea poco probable que la Base de Datos sufra cambios frecuentes pero de cualquier forma es importante mantener la documentacion sincronizada con lo que es ofrecido por el codigo fuente.

El proceso mediante el cual se genera la documentacion en OpenStack es muy sencillo, ya que utiliza tox. Tox se define como una herramienta escrita en Python para automatizar y estandarizar pruebas en Python. Su comportamiento se especifica a traves de un archivo de configuracion llamado tox.ini donde se define la manera en que se genera los ambientes virtuales utilizados para ejecucion de pruebas unitarias y funcionales o como es nuestro caso, la generacion de documentacion.

Este archivo tiene una seccion donde se enlista los ambientes virtuales a ser creados, para el caso de Neutron solo se crearan cuatro ambientes virtuales:

  • docs: Utilizado para la generacion de documentacion del proyecto
  • py34: Utilizado para la ejecucion de las pruebas unitarias y funcionales para la version de Python 3.4
  • py27: Utilizado para la ejecucion de las pruebas unitarias y funcionales para la version de Python 2.7
  • pep8: Utilizado para la validacion de reglas para el estilo de programacion

neutron/tox.ini

[tox]
envlist = docs,py34,py27,pep8
...

Durante la ejecucion inicial se crean ambientes virtuales(en caso de no existir) y dentro de cada uno de ellos se instala los modulos enlistados en los archivos de requirements.txt y test-requirements.txt. Este proceso solo abarca aquellos modulos de python necesarios para la ejecucion de tox, todas aquellas dependencias que de sistema tendran que ser instaladas por separado, como es el caso de las bibliotecas de desarrollo de python( # apt install python-dev || dnf install python-devel) entre otras.

[testenv]
...
install_command =
                  constraints: {[testenv:common-constraints]install_command}
                  pip install -U {opts} {packages}
deps = -r{toxinidir}/requirements.txt
       -r{toxinidir}/test-requirements.txt
...
[testenv:common-constraints]
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
...

Dentro del archivo podemos observar el comando utilizado para la generacion de documentos.

[testenv:docs]
commands = sphinx-build -W -b html doc/source doc/build/html

De tal forma que al ejecutar $ tox -e docs se creara un ambiente virtual en dentro de la carpeta ~/.tox/docs con todas los modulos necesarios para generacion de documentos y dentro de el se ejecutara el comando sphinx-build -W -b html doc/source doc/build/html. En cuanto a los parametros utilizados, W permite cambiar los mensajes de Warning por Errores, b define el builder a ser utilizado y los dos argumentos, el primero define la carpeta donde se localiza la documentacion en formato Markdown y el segundo es la carpeta para los archivos generados.

Como he mencionado previamente, sphinx es un modulo de python que nos permite generar documentacion a partir de archivos escritos en formato Markdown. Al igual que tox, su funcionamiento se basa en un solo archivo que contiene los valores de configuracion, este archivo se llama conf.py y debe localizarse dentro de la carpeta utilizada como fuente, en nuestro caso doc/source/conf.py.

Por ultimo, es importante mencionar que sphinx es una herramienta poderosa que permite extender su funcionalidad mendiante el uso de extensiones, estas son anexadas dentro del archivo de configuracion
conf.py

...
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc',
              'sphinx.ext.coverage',
              'sphinx.ext.ifconfig',
              'sphinx.ext.pngmath',
              'sphinx.ext.graphviz',
              'sphinx.ext.todo',
              'schemadisplay_sphinx',
              'oslosphinx']
...

Primeras impresiones de python-openstacksdk

Actualmente he realizado algunas modificaciones en un proyecto el cual me ha permitido conocer de cerca algunas de las funciones de python-openstacksdk, por lo que me gustaría compartir mis primeras observaciones.  El primer paso es su instalación, en este caso para no complicarse, utilizaremos un manejador de paquetes como es el caso de pip.

Instalación de dependencias

$ pip install openstacksdk

Una vez instalada la biblioteca junto con todas sus dependencias podemos utilizar dentro del código de nuestra aplicación. Lo primero y más importante es necesario crear un objeto el cual nos permitirá comunicarnos con nuestra implementación de OpenStack.

Conexion

from openstack import connection
auth_args = {
    'auth_url': 'http://localhost:5000/v3',
    'project_name': 'admin',
    'username': 'admin',
    'password': 'secure',
}
conn = connection.Connection(**auth_args)

Para conocer los parametros de conexion, es necesario navegar en la documentación oficial.

Aunque los argumentos del constructor de este objeto están ampliamente documentados, existe un poco de ambigüedad respecto a los soportados por auth_args, para ello es necesario buscar dentro del código fuente. Una vez que hemos revisado algo del código, podemos observar que los valores aceptados varían de acuerdo a la versión de Keystone que queramos consumir(v2 o v3) y al método de autenticación a ser usado(password o token), estas son las combinaciones existentes al momento de la publicación.

Combinacion URL
Password V2 https://github.com/openstack/python-openstacksdk/blob/master/openstack/auth/identity/v2.py#L115-L127
Token V2 https://github.com/openstack/python-openstacksdk/blob/master/openstack/auth/identity/v2.py#L170-L180
Password V3 https://github.com/openstack/python-openstacksdk/blob/master/openstack/auth/identity/v3.py#L253-L269
Token V3 https://github.com/openstack/python-openstacksdk/blob/master/openstack/auth/identity/v3.py#L295-L309

Una vez que se establece una conexión se puede realizar una serie de operaciones. Operaciones como la creación, eliminación, actualización y enlistado de usuarios, roles, proyectos, credenciales, dominios, endpoints, etc.

Ejemplo de listado de proyectos

...
projects = conn.identity.list_projects()
...

Observaciones

En el transcurso del desarrollo de la aplicación, parece ser que carece de algunas operaciones que no son de uso frecuente o común para las aplicaciones orientadas en la nube. Por ejemplo, referente a la manera de conectarse parece estar restringida solo a nubes existentes previamente configuradas de tal forma que, valores como OS_TOKEN y OS_URL son inválidos.

Por último resulta incierto la manera de asociar objetos, por ejemplo, asignar un rol a una cuenta o un grupo. Quizá la falta de documentación o el acceso a la documentación existente no es del todo eficiente. De cualquier forma, estas carencias tanto de documentación como de código fuente, refleja la necesidad de apoyo a este útil proyecto.

OpenStack Big Tent

Nota:  Este artículo está basado en la publicación del blog de Rich Bowen.

Históricamente, cada nuevo release realizado por la comunidad de OpenStack se oficializaba algún proyecto, es decir, dejaba de formar parte de los proyectos de incubación.

Nombre Fecha Nuevos proyectos
Austin 21 octubre 2010 Nova, Swift
Bexar 3 febrero 2011 Glance
Cactus 15 abril 2011
Diablo 22 septiembre 2011
Essex 5 abril 2012 Horizon, Keystone
Folsom 27 septiembre 2012 Quantum, Cinder
Grizzly 4 abril 2013 Quantum, Cinder
Havana 17 octubre 2013 Ceilometer & Heat
Icehouse 17 abril 2014 Trove
Juno 16 octubre 2014 Sahara
Kilo 30 abril 2015 Ironic
Liberty 15 octubre 2015  “Big Tent”
Mitaka abril 2016
N octubre 2016

Con el fin de dar una mayor claridad de qué proyectos son considerados como parte esencial de OpenStack el comité Tecnico decidió crear un mejor enfoque bajo el término de “Big Tent”.  Para que un proyecto sea considerado como parte de este “Big Tent”, este debe cumplir con cuatro características importantes:

1) Alinearse con la Misión de OpenStack.

2) Obedece la Manera de trabajo de OpenStack.

3) Esforzarse en mantener interoperabilidad entre los componentes de OpenStack.

4) Estar sujeto a la dirección del Comité Tecnico.

Por último, cabe mencionar una vez aprobado el proyecto éste será etiquetado por el Comité y publicado desde su página oficial.

Network Managers (Legacy networking)

Durante el proceso de creación de instancias, el nodo de cómputo asigna una IP privada a cada máquina virtual. Este servicio diferencia entre una IP estática(Fixed IP) y una IP dinamica(Floating IP). Las IPs estáticas son aquellas que permanecen asignadas a lo largo de su vida operativa de una máquina virtual . Por otra parte, las IPs dinámicas o flotantes pueden ser asignadas con una máquina virtual por un periodo de tiempo definido.

Existen tres opciones (FlatManager, FlatDHCPManager y VlanManager) soportadas como manejadores de red para Nova, estas proveen redes virtuales para que las máquinas virtuales puedan comunicarse entre distintos nodos de cómputo y/o con la red publica. Además, han sido descritas hace tiempo en artículos de Mirantis, sin embargo considero conveniente escribir al respecto. Estos tipos de redes pueden coexistir en una implementación, pero debido a que no se puede seleccionar el tipo de rede para cada proyecto, no es posible seleccionar varios tipos para un nodo de cómputo y es por eso que solo una clase puede ser especificada en el archivo de configuración de nova para el nodo de cómputo y su elección depende de las necesidades del negocio. Estas opciones comparten la necesidad de ser administradas y monitoreadas por el operador de la nube.

Todos los administradores de red operan tanto en modo single-host como multi-host(variable de configuracion multi_host). La diferencia entre cada uno es la cantidad de servicios de nova-network que son ejecutados, mientras que single-host, levanta un solo servicio de nova-network ofreciendo servicios como Network Address Translation (NAT), DHCP, y DNS para las máquinas virtuales, para el modo de multi-host cada nodo de cómputo levanta su propio servicio de nova-network.  Esta última opción, permite tener alta disponibilidad y evitando cuellos de botella en el tráfico de red.

nova.network.manager.FlatManager

flatnetwork-diagram-1

La primera clase a analizar es FlatManager, entre las posibles razones para utilizar dicha clase es la existencia de un servicio externo de DHCP y la simplicidad de su uso. Esta opción no ofrece ningún bridge, su creación en cada nodo de cómputo, es responsabilidad del operador y se define en el archivo de configuración con la variable flat_network_bridge. Estos son los cambios necesarios en el archivo de configuración:

/etc/nova/nova.conf

[DEFAULT]
...
network_api_class = nova.network.api.API
public_interface = eth0
flat_network_bridge = br100
network_manager = nova.network.manager.FlatManager
dhcp_domain = novalocal

Es necesario reiniciar el servicio para que los cambios tomen efecto( el nombre del servicio y la forma dependerá de la distribución de Linux que se está usando). Una vez que el servicio inicie con los valores previamente configurados es necesario especificar el rango de redes. Estas direcciones de IP serán inyectadas en la imagen utilizada en la construcción de la máquina virtual. En otras palabras, cada instancia recibe una IP fija de un conjunto disponible.

# service nova-network restart
$ nova-manage network create --label=demo-net --bridge=br100 --multi-host=T --fixed_range_v4=203.0.113.24/29

nova.network.manager.FlatDHCPManager

flat-dhcp-networking-diagrams-4

La clase FlatDHCPManager es similar a la clase FlatManager con la diferencia de que OpenStack levanta un servicio de DHCP a través del servicio de dnsmasq. Al igual que FlatManager, todas las instancias son conectadas a un único bridge del nodo de computo. El servicio de computo asigna una IP estática a cada instancia y dnsmasq registra la dirección de IP con el MAC ID de la máquina virtual para garantizar que cada instancia mantenga su IP estática. Cabe señalar que el servicio de dnsmasq no toma parte del proceso de asignación de direcciones IP, solo lleva el registro(por medio del comando dhcpdiscover) en un archivo que se almacena en la carpeta definida por la variable networks_path del archivo de configuración( por lo general /var/lib/nova/networks/), de cada nodo de cómputo.

/etc/nova/nova.conf

[DEFAULT]
...
network_api_class = nova.network.api.API
public_interface = eth0
flat_interface = eth0
flat_network_bridge = br100
network_manager = nova.network.manager.FlatDHCPManager

También es necesario reiniciar los servicios y crear los rangos de red.

# service nova-network restart
$ nova-manage network create --label=demo-net --bridge=br100 --multi-host=T --fixed_range_v4=203.0.113.24/29

nova.network.manager.VlanManager

vlanmanager-2-hosts-2-tenants

Esta es la clase utilizada por el servicio de Nova Network por defecto. En este modo, los operadores de la nube deben crear una VLAN y un bridge para cada proyecto. En cuanto a hardware, se requiere que el switch utilizado entre varios nodos de cómputo soporte VLAN tagging (IEEE 802.1Q). El rango de IPs privadas son solo accesibles dentro de la VLAN. Para que un usuario pueda acceder a sus máquinas virtuales en cada proyecto, es necesario crear una instancia VPN(llamada cloudpipe).

/etc/nova/nova.conf

[DEFAULT]
...
network_api_class = nova.network.api.API
public_interface = eth0
vlan_interface = eth0
flat_network_bridge = br100
network_manager = nova.network.manager.VlanManager

De igual forma, el rango de IPs es especificado por el administrador para ser asignado(el rango de IPs) dinámicamente a un proyecto cuando es necesario.

# service nova-network restart
$ nova-manage network create --fixed_range_v4=10.0.1.0/24 --vlan=102

Para mayor información, está disponible la guia oficial de administración.

Tareas periódicas de Nova

Actualmente he estado trabajando en un proyecto que me permite revisar a detalle el código fuente de OpenStack, por lo que me he topado con una funcionalidad que me ha parecido interesante. Esta es la ejecucion de tareas periódicas en el proyecto de Nova, y si bien la documentación oficial hace una analogia de estas con los cron jobs de Linux vale la pena profundizar un poco mas sobre el tema.

Su funcionalidad es sencilla, como su nombre lo indica son funciones que se ejecutan con cierto grado de periodicidad. Estas funciones van desde la actualización de los estados de las maquinas hasta la verificación del caché de que almacena las imagenes. En cada función se define, entre otras cosas, la frecuencia de ejecución y si es necesario que sea ejecutada de forma inmediata.

A nivel de código podemos encontrar su implementación en el proyecto de oslo.service como un metodo decorador de funciones. Este decorador define el comportamiento de cada función, ademas de proveer la conexion entre el valor de configuración provisto por el usuario y la definicion del tarea periodica, un claro ejemplo es la función que sincroniza los estados de las maquinas.

Cada una de las funciones es registradas a traves de una clase Manager, que a su vez hace uso de los metodos definidos por una metaclase llamada _PeriodicTasksMeta en su metodo _add_periodic_task.

Por último y una vez registradas cada una de las funciones es necesario conocer el motor que manda ejecutar cada una de ellas de forma periódica. De igual forma estas son ejecutadas por la clase Manager en su funcion periodic_tasks que a su vez manda llamar a clase padre en su metodo run_periodic_tasks este ultimo iterando y ejecutando cada elemento de la lista de funciones. Y si se estan preguntando quien manda llamar a esta clase Manager, cada servicio(nova-api, nova-cert, nova-compute, nova-conductor, nova-consoleauth, nova-network, nova-novncproxy, nova-scheduler) tienen definida una propiedad que hace referencia a una subclase de esta clase Manager, es desde ahí donde se hace la llamada a sus tareas periodicas.

Esta funcionalidad está habilitada por defecto y puede ser deshabilitada via archivo de configuracion en la variable periodic_enable de la seccion DEFAULT del archivo nova.conf.

Utilizando nova-docker y nova-compute-lxd drivers

Hace tiempo estuve leyendo un articulo de Lars Kellogg Stedman donde menciona la posibilidad de utilizar varios “hipervisores” en el mismo nodo de computo, por medio de la instalación y configuración de nova-docker driver en conjunto con el levantamiento de un servicio adicional de nova-compute, el cual se encarga de despachar las peticiones por los usuarios para ese hipervisor en particular. Esta información esta basada en Fedora 21 y hace uso de los servicios de systemd, pero puede ser adaptado a cualquier otra distribución de Linux.

Este articulo pretende enlistar aquellos pasos necesarios para lograr el mismo objetivo en Ubuntu 14.04 LTS. Ademas de incluir Docker, se incluye los pasos necesarios para agregar LXD como otra alternativa mas en la lista de “hipervisores”.

Nota : Se asume la correcta instalación y configuración de otros servicios de OpenStack en el servidor.

Antes que nada es necesario instalar algunas dependencias y servicios que serán utilizados mas tarde, por lo cual se necesita validar conexión a internet y que la cuenta utilizada tenga permisos de administrador sobre la maquina.

Instalación de dependencias

sudo apt-get update -y
sudo apt-get install -y git python-dev crudini
 
# Instalacion de pip
curl https://bootstrap.pypa.io/get-pip.py | sudo python
 
# Instalacion de LXD
sudo add-apt-repository -y ppa:ubuntu-lxc/lxd-git-master
sudo apt-get update -y
sudo apt-get install -y lxd
 
# Instalacion de Docker
curl -sSL https://get.docker.com/ubuntu/ | sudo sh

Una vez instaladas algunas dependencias y servicios, realizaremos la descarga e instalación de los drivers para la comunicación de nova con el “hipervisor”. Ya que no hay garantia de que estos drivers puedan estar incluidos en los paquetes o dependencias de los paquetes de OpenStack es mas sencillo instalarlos de forma manual. Para ello se necesita descargar el código fuente (clonando el repositorio) e instalarlo por medio de pip o simplemente utilizando python setup install.

Instalación de drivers

git clone https://github.com/stackforge/nova-docker /tmp/nova-docker
git clone https://github.com/lxc/nova-compute-lxd /tmp/nova-compute-lxd
 
pushd /tmp/nova-docker
git checkout stable/kilo
cp etc/nova/rootwrap.d/docker.filters /etc/nova/rootwrap.d
pip install .
popd
 
pushd /tmp/nova-compute-lxd
git checkout stable/kilo
cp etc/nova/rootwrap.d/lxd.filters /etc/nova/rootwrap.d
pip install .
popd

Cabe mencionar que el branch utilizado en esta ocasión es para release de Kilo, esto puede variar con respecto al release utilizado, y es necesario incluir los filtros que serán utilizados por rootwrap.

El siguiente paso consiste en configurar cada servicio para que utilize un driver especifico y así conectarse con el hipervisor correspondiente. Cada servicio utilizara un valor de host diferente para poder ser diferenciados y require los valores necesarios para conectarse con el servidor de cola de mensajes.

Configuración de drivers

# Configuracion de nova-docker
touch /etc/nova/nova-docker.conf
chown nova:nova /etc/nova/nova-docker.conf
 
crudini --set /etc/nova/nova-docker.conf DEFAULT host docker${CONFIGURATION}
crudini --set /etc/nova/nova-docker.conf DEFAULT compute_driver novadocker.virt.docker.DockerDriver
crudini --set /etc/nova/nova-docker.conf DEFAULT state_path /var/lib/nova-docker
 
crudini --set /etc/nova/nova-docker.conf DEFAULT rpc_backend rabbit
crudini --set /etc/nova/nova-docker.conf oslo_messaging_rabbit rabbit_host ${MESSAGE_BROKER_HOSTNAME}
crudini --set /etc/nova/nova-docker.conf oslo_messaging_rabbit rabbit_userid openstack
crudini --set /etc/nova/nova-docker.conf oslo_messaging_rabbit rabbit_password ${RABBIT_PASS}
 
# Configuracion de nova-compute-lxd
touch /etc/nova/nova-compute-lxd.conf
chown nova:nova /etc/nova/nova-compute-lxd.conf
 
crudini --set /etc/nova/nova-compute-lxd.conf DEFAULT host lxd${CONFIGURATION}
crudini --set /etc/nova/nova-compute-lxd.conf DEFAULT compute_driver nclxd.nova.virt.lxd.LXDDriver
crudini --set /etc/nova/nova-compute-lxd.conf DEFAULT state_path /var/lib/nova-compute-lxd
 
crudini --set /etc/nova/nova-compute-lxd.conf DEFAULT rpc_backend rabbit
crudini --set /etc/nova/nova-compute-lxd.conf oslo_messaging_rabbit rabbit_host ${MESSAGE_BROKER_HOSTNAME}
crudini --set /etc/nova/nova-compute-lxd.conf oslo_messaging_rabbit rabbit_userid openstack
crudini --set /etc/nova/nova-compute-lxd.conf oslo_messaging_rabbit rabbit_password ${RABBIT_PASS}

Por ultimo y no menos importante, es necesario registrar los servicios para que estos puedan ser levantados durante el arranque de la maquina por upstart. Para lograrlo se necesita agregar las instrucciones de arranque del servicio en archivos localizados en el directorio /etc/init/.

Configuration de servicios

cat <<EOL > /etc/init/nova-docker.conf
# vim: set ft=upstart et ts=2:
description "Nova compute docker worker"
author "Victor Morales <electrocucaracha@gmail.com>"
 
start on runlevel [2345]
stop on runlevel [!2345]
 
exec start-stop-daemon --start --chuid root --exec /usr/bin/nova-compute -- --config-file=/etc/nova/nova-docker.conf
EOL
 
cat <<EOL > /etc/init/nova-compute-lxd.conf
# vim: set ft=upstart et ts=2:
description "Nova compute LXD worker"
author "Victor Morales <electrocucaracha@gmail.com>"
 
start on runlevel [2345]
stop on runlevel [!2345]
 
exec start-stop-daemon --start --chuid root --exec /usr/bin/nova-compute -- --config-file=/etc/nova/nova-compute-lxd.conf
EOL
 
service nova-docker restart
service nova-compute-lxd restart

Una vez que los servicios inicien y puedan comunicarse con el servidor de cola de mensajes, serán registrados dentro del catalogo de “hipervisores” disponibles para OpenStack.

Cloud-Driven Development

Esta es una propuesta para la mejora en la eficiencia del desarrollo de software:

Summary

Even today, environments dedicated entirely to support projects during its development and/or testing phases are under-utilised during non-working hours. No matter the use of those servers they’re always consuming energy for its operation, resulting in infrastructure operating costs for the company. Adapting software development processes in such a way that can only consume resources(servers) on demand during development and testing phases can significantly reduce costs and prevents information loss for an application.

Problem/Opportunity

The process to create and configure environments is traditionally assigned to a single person and managed through a ticketing system whereby time and effort are estimated. In other words, the operator or responsible will only have predefined period of time for setting up an environment requested by an end user(e. g. developer, tester). This is why provisioning activities are made only once and usually at the beginning of a project. But the working environment creation can be the easiest way to do a sanity check of the whole project and verify its correct functionality, this process must not have workarounds or undocumented steps. Additionally, the earlier detection of defects can simplify its resolution and reduce costs for the software development process. Therefore, creating working environments periodically can help to detect defects no matter the stage of the project.

Development and Testing environments are mainly used during working hours, meaning that almost two-thirds of their time the servers are in a state of inactivity. Simple acts such as turning servers off when they are not used can reduce infrastructure operating costs. In order to make this a new habit, these actions must be done on a regular basis.

Solution

Vagrant provides easy to configure, reproducible, and portable work environments built on top of industry-standard technology and controlled by a single consistent workflow to help maximize the productivity and flexibility of you and your team. Vagrant has the ability to manage virtual machines such as VirtualBox, VMware, KVM, and others. Lastly, boxes are the package format for Vagrant environments.

A base box is created from a minimal Operative System with the minimum set of software required for Vagrant to function.  Vagrant uses industry-standard provisioning tools such as shells scripts, Chef or Puppet to automatically install and configure software on the machine. As result, developers, testers and operators are able to create disposable and consistent environments for development and testing.

Agile methodologies promotes adaptive planning, evolutionary development, early delivery, continuous improvement, and encourages rapid and flexible response to change. The main goal for short iterations is to release working item(s) to product owners and communicate the progress on the project with stakeholders and project sponsors.

This document suggests doing changes into day-to-day activities of developer and tester, in a way that at the beginning of the day they must recreate a work environment for getting the latest changes. Having completed their work, only those desired changes should be backed up to proceed to release resources used (i. e. destroy the work environment created at the beginning). If those actions are performed daily by the team, anyone can be joined and start working on the project without assistance, since anytime can request the creation of an work environment and it will have latest changes of the project setup and the project itself. Furthermore, those changes that were not backing up previously are going to reflect malfunctioning the next time that someone creates a work environment, as consequence, this new process helps to fail fast and quickly realize that something is not working.

In order to demonstrate how this methodology works, I’ll take the OpenStack development as an example. OpenStack is an open source infrastructure as a service (IaaS) initiative for creating and managing large groups of virtual private servers in a data center. According to their activity reports during the last 7 days 553 commits have been submitted, resulting in around 80 commits per day. That is why an OpenStack developer can get different results of the work environment based on the day that was created.

The devstack-vagrant project allows to setup an OpenStack work environment and retrieve latest changes of each OpenStack component using Vagrant boxes. Using Cloud-Driven Development, an OpenStack developer must recreate an OpenStack work environment with devstack-vagrant project at the beginning of the day. This new work environment will remain active until all changes have been tested and verified properly. Once all desired changes have been submitted to the OpenStack repositories, before ending the day, the work environment must be destroyed to release any resource.

Results

Adapting agile methodologies to consume only the resources that are needed can results in:

  1. By using cloud computing model of “pay as you go” only during working hours can reduce infrastructure costs for development and test teams.
  2. Every time a work environment is created there is an opportunity to early detect failures in the project.
  3. Performing regular backups of the project reduces time for recovering and impact caused by a disaster.
  4. New members can quickly start contributing into the project.