Esta web utiliza cookies, puedes ver nuestra política de cookies, aquí Si continuas navegando estás aceptándola

Gestor de hipervisores mediante xmpp y libvirt


En este artículo aprenderemos con instalar y configurar Archipel, este nos permitirá gestionar varios hipervisores mediante un nexo central, en cada uno de los hipervisores tendremos un agente que informará a Archipel sobre el estado del hipervisor y de las máquinas virtuales, toda la comunicación entre los agentes y Archipel se hará mediante el servidor xmpp, a su vez dispondremos de un servidor web donde alojaremos la interfaz de Archipel.

En este video podemos darle un vistazo rápido a la interfaz.

Debo confesar que este software no lo considero lo suficientemente maduro como para utilizarlo en producción por su multiples bugs y funcionalidades que funcionan de forma parcial.

 

 

 

 


Puesta a punto del sistema(estos pasos se realizarán tanto en el servidor de Ejabberd, Apache y el Agente):

emerge --sync
emerge --update -nd world
emerge --depclean
revdep-rebuild

Instalación del servidor de XMPP, Ejabberd:

echo "net-im/ejabberd mod_irc mod_muc mod_pubsub mod_statsdx" > /etc/portage/package.use/ejabberd
emerge net-im/ejabberd
rc-update add ejabberd default

 

Generamos el certificado de Ejabberd:

cd /tmp
openssl genrsa -out ejabberkey.key 2048
openssl req -new -key ejabberkey.key -out ejabberkey.csr
openssl x509 -req -days 3650 -in ejabberkey.csr -signkey ejabberkey.key -out ejabberkey.crt
cat ejabberkey.key >> ejabber.pem
cat ejabberkey.crt >> ejabber.pem
cp ejabber.pem /etc/jabber/ejabberd.pem

 

Compilación de módulo externo:

Archipel utiliza un módulo de ejabberd que no está disponible mediante USE flags así que lo compilaremos manualmente.

cd /tmp
svn co https://svn.process-one.net/ejabberd-modules
cd ejabberd-modules/mod_admin_extra/trunk
./build.sh
cp ebin/mod_admin_extra.beam /usr/lib64/erlang/lib/ejabberd-*/ebin/

 

Configuración de Ejabberd:

Configuramos ejabberd con el dominio a servir y el usuario de administración(admin, hypervisor):

vi  /etc/jabber/ejabberd.cfg

{hosts, ["alfaexploit.com"]}.

  {5222, ejabberd_c2s, [
            {certfile, "/etc/jabber/ejabberd.pem"},
            
{s2s_certfile, "/etc/jabber/ejabberd.pem"}.

{acl, admin, {user, "admin", "alfaexploit.com"}}.

{acl, admin, {user, "hypervisor", "alfaexploit.com"}}.
%% {acl, admin, {user, "hypervisor-x", "alfaexploit.com"}}.
%% {acl, admin, {user, "hypervisor-n", "alfaexploit.com"}}.

{language, "en"}.

 {mod_pubsub,   [ % requires mod_caps
          {access_createnode, pubsub_createnode},
          {ignore_pep_from_offline, true},
          {last_item_cache, false},
          {plugins, ["flat", "hometree", "pep"]},
          {max_items_node, 1000}
         ]},

 

Arrancamos el servidor de xmpp:

/etc/init.d/ejabberd start

 

Comprobamos el estado de todos los servicios necesarios:

/etc/init.d/ejabberd status

 

Asignamos un password al usuario admin:

ejabberdctl register admin alfaexploit.com password

 

En estos momentos ya podremos acceder a la interfaz de gestión de Ejabberd:

http://SERVERIP:5280/admin
 


Ahora procedemos con la instalación del agente.

Instalación de Qemu como hypervisor y libvirt para gestionarlo:

vi /etc/make.conf
USE="mmx sse sse2 libvirtd virt-network qemu"
QEMU_SOFTMMU_TARGETS="i386 x86_64"
QEMU_USER_TARGETS="i386 x86_64"

echo "app-emulation/libvirt lvm pcap python qemu sasl macvtab" > /etc/portage/package.use/libvirt
echo "app-emulation/qemu vhost-net" > /etc/portage/package.use/qemu

emerge app-emulation/libvirt app-emulation/qemu net-firewall/iptables net-misc/bridge-utils sys-apps/dbus dev-vcs/subversion virtual/python-imaging dev-python/g-pypi dev-python/sqlite3dbm dev-python/libvirt-python

 

Arranque del servicio de virtualización:

/etc/init.d/libvirtd start
rc-update add libvirtd default

 

Seleccionamos python2.7 como interprete de python por defecto:

eselect python list
Available Python interpreters:
  [1]   python2.7
  [2]   python3.3 *

eselect python set 1

 

Instalamos las dependencias del agente:

emerge dev-python/setuptools
easy_install apscheduler xmpppy sqlalchemy numpy python-magic

 

Compilamos el agente:

cd /usr/src
git clone https://github.com/ArchipelProject/Archipel.git
cd Archipel
cd ArchipelAgent/
./buildAgent -d
MESSAGE: All action performed
archipel-initinstall

 

Configuramos el hosts de tal modo que la ip de nuestro agente resuelva el nombre del dominio xmpp a la ip del servidor de Ejabberd:

vi /etc/hosts
EJABBERD_IP        alfaexploit.com

 

Configuramos el agente:

vi /etc/archipel/archipel.conf

[DEFAULT]
xmpp_server                 = alfaexploit.com
archipel_folder_lib         = /var/lib/archipel/
archipel_general_uuid       = 7e1b0402-9a79-44a3-a26f-54d28eca4bfb
archipel_folder_data        = /vm/

[GLOBAL]
xmpp_pubsub_server          = pubsub.%(xmpp_server)s
archipel_root_admins        = [email protected]%(xmpp_server)s
machine_ip                  = IP_AGENT
use_avatar                  = True
machine_avatar_directory    = %(archipel_folder_lib)s/avatars
libvirt_uri                 = qemu:///system
module_loading_policy       = restrictive
stateless_node              = False

[VCARD]
orgname     = Archipel Corp
orgunit     = Dev
userid      = [email protected]
locality    = San Francisco
url         = http://archipelproject.org
categories  = Archipel

[HYPERVISOR]
hypervisor_xmpp_jid         = [email protected]%(xmpp_server)s
hypervisor_xmpp_password    = XXXXXXXXX
hypervisor_name             = auto
hypervisor_database_path    = %(archipel_folder_lib)s/hypervisor.sqlite3
hypervisor_default_avatar   = defaulthypervisor.png
name_generation_file        = %(archipel_folder_lib)s/names.txt
hypervisor_permissions_database_path = %(archipel_folder_lib)s/permissions.sqlite3

[VIRTUALMACHINE]
vm_base_path                    = %(archipel_folder_data)s/drives
vm_default_avatar               = defaultvm.png
xmpp_password_size              = 32
maximum_lock_time               = 1
vm_permissions_database_path    = /permissions.sqlite3
allow_blank_space_in_vm_name    = True
enable_block_device_access      = True
disable_screenshot              = False

[LOGGING]
logging_level               = debug
log_pubsub_item_expire      = 3600
log_pubsub_max_items        = 1000
logging_file_path           = /var/log/archipel/archipel.log
logging_max_bytes           = 5000000
logging_backup_count        = 5
logging_date_format         = %Y-%m-%d %H:%M:%S
logging_formatter           = %(levelname)s::%(asctime)s::%(filename)s:%(lineno)s::%(message)s
xmpppy_debug                = False

[MODULES]
action_scheduler            = True
geolocalization             = True
hypervisor_health           = True
hypervisor_network          = True
hypervisor_vmcasts          = True
iphone_notification         = False
oomkiller                   = True
snapshoting                 = True
storage                     = True
virtualmachine_appliance    = True
vnc                         = True
xmppserver                  = True
platformrequest             = False
vmparking                   = True

[HEALTH]
health_database_path        = %(archipel_folder_lib)s/statscollection.sqlite3
health_collection_interval  = 5
max_rows_before_purge       = 50000
max_cached_rows             = 200

[STORAGE]
iso_base_path               = %(archipel_folder_data)s/iso
use_metadata_preallocation  = True
qemu_img_bin_path           = /usr/bin/qemu-img
golden_drives_dir           = %(archipel_folder_data)s/goldens

[GEOLOCALIZATION]
localization_mode                           = auto
localization_latitude                       = 0.0
localization_longitude                      = 0.0
localization_service_url                    = ipinfodb.com
localization_service_request                = /ip_query.php
localization_service_method                 = GET
localization_service_response_root_node     = Response

[VMCASTING]
vmcasting_database_path     = %(archipel_folder_lib)s/vmcasting.sqlite3
repository_path             = %(archipel_folder_data)s/repo
temp_path                   = %(archipel_folder_data)s/tmp
own_vmcast_name             = Local VM casts of $HOSTNAME
own_vmcast_description      = This is the own vmcast feed of the hypervisor $HOSTNAME
own_vmcast_uuid             = %(archipel_general_uuid)s
own_vmcast_url              = http://127.0.0.1:8088/vmcasts/
own_vmcast_file_name        = rss.xml
own_vmcast_lang             = en-us
own_vmcast_path             = %(archipel_folder_data)s/vmcasts/
own_vmcast_refresh_interval = 60
disks_extensions            = .qcow2;.qcow;.img;.iso
should_gzip_drives          = True
ignore_user_gzip_choice     = False

[IPHONENOTIFICATION]
credentials_key             = YOUR CRED HERE

[OOMKILLER]
database                    = %(archipel_folder_lib)s/scheduler.sqlite3

[XMPPSERVER]
use_xmlrpc_api      = False
xmlrpc_host         = %(xmpp_server)s
xmlrpc_port         = 4560
xmlrpc_sslonly      = False
xmlrpc_user         = admin
xmlrpc_password     = password
auto_group          = False
auto_group_name_virtualmachines     = All Virtual Machines
auto_group_name_hypervisors         = All Hypervisors
auto_group_filter   = all

[VNC]
vnc_certificate_file        = /etc/archipel/vnc.pem
vnc_only_ssl                = False
vnc_enable_websocket_debug  = False

[NETWORKS]
libvirt_nw_filters_path     = /etc/libvirt/nwfilter

[VMPARKING]
database                    = %(archipel_folder_data)s/shared_parking.sqlite3

 

NOTA: El nombre del Hipervisor es totalmente arbitrario, en mi caso se llamará Jupiter

 

Descargamos la iso de Gentoo y Debian para que luego estén disponibles desde la interfaz de Archipel:

cd /vm/iso
wget http://distfiles.gentoo.org/releases/amd64/autobuilds/current-iso/install-amd64-minimal-20140320.iso
wget http://cdimage.debian.org/debian-cd/7.4.0/amd64/iso-cd/debian-7.4.0-amd64-netinst.iso

 

Configuramos en el servidor de ejabberd los usuarios y los grupos que necesita Archipel para funcionar:

archipel-tagnode [email protected] --password=YOURPASSWORD --create

 

NOTA: En probable que casque, en mi caso detecté el problema monitorizando los logs:

tail -f /var/log/jabber/ejabberd.log
=ERROR REPORT==== 2014-03-23 20:41:13 ===
E(<0.309.0>:mod_pubsub:3863) : transaction return internal error: {aborted,
                                                                   {bad_type,
                                                                    {pubsub_state,
                                                                     {{"admin",
                                                                       "alfaexploit.com",
                                                                       []},
                                                                      10},
                                                                     10,[],
                                                                     owner,
                                                                     []}}}

 

Para solventarlo debemos borrar las tablas conflictivas desde la interfaz web de administración de ejabberd:

http://SERVERIP:5280/admin

 

En mi caso estas son las tablas que tuve que borrar:

pubsub_state

pubsub_item

 

Creamos el resto de cuentas:

archipel-rolesnode [email protected] --password=YOURPASSWORD --create
SUCCESS: pubsub node /archipel/roles created

 

archipel-adminaccounts [email protected] --password=YOURPASSWORD --create
SUCCESS: pubsub node /archipel/adminaccounts created

 

Arrancamos el agente:
NOTA: En Gentoo no tenemos el script, tendremos que arrancar el agente manualmente:

runarchipel
tail -f /var/log/archipel/archipel.log

 

Comprobamos que nuestro Hypervisor está logado:

ejabberdctl connected_users
[email protected]/Jupiter

 

Realizamos algunos tests:

archipel-testxmppserver [email protected] --password=YOURPASSWORD

Si no hemos habilitado el soporte de XML-RPC en ejabberd a la hora de compilar los dos últimos tests cascarán.

 


El cliente es 100% JavaScript lo que implica que no es necesario soporte para php ni nada por el estilo en el servidor web, tan solo nos bajamos los ficheros, los colocamos en un lugar accesible por Apache/Nginx... y listo calisto :) pero hay una dependencia, Capuccino que precisa de Java para su compilación, una vez instalado se podrá eliminar.

 

Instalamos las dependencias en el servidor web:

emerge dev-java/oracle-jdk-bin virtual/rubygems
gem19 install jake

 

Nos bajamos el código de la interfaz web de Archipel:

cd /usr/src
git clone https://github.com/ArchipelProject/Archipel.git
cd Archipel

 

Inicializamos los módulos:

git submodule update --init

 

NOTA: Si fuese necesario reinicializarlos:

rm .submodules_initialized

 

Compilamos e instalamos:

cd ArchipelClient
xport NARWHAL_ENGINE=rhino
./bootstrap

 Installation information
   - build Cappuccino            : True
   - build GrowlCappuccino       : True
   - build VNCCappuccino         : True
   - build StropheCappuccino     : True
   - build TNKit                 : True
   - build LPKit                 : True
   - build Archipel Client       : True
   - apply Cappuccino            : True
   - export to                   : /root/client

`(pipe) too many open files`: Try to increase your ulimit -n value (related to open file numbers) with `ulimit -n 512`.

 

Instalamos el servidor web:

emerge www-servers/apache
mkdir /root/vhosts
mv /etc/apache2/vhosts.d/* /root/vhosts/

 

vi /etc/apache2/vhosts.d/00_Archipel.conf

Listen 80
<VirtualHost *:80>
        ServerName *
        ServerAdmin [email protected]
        DocumentRoot /var/www/Archipel
        DirectoryIndex index.html
        ErrorLog "/var/log/apache2/error_archipel.log"
        CustomLog "/var/log/apache2/access_archipel.log" combined
        LogLevel debug

        <Directory />
            Order Deny,Allow
            Deny from all
        </Directory>

        <Directory "/var/www/Archipel">
                Options -Indexes -FollowSymLinks
                AllowOverride None
                Order Deny,Allow
                Allow from all
        </Directory>
</VirtualHost>

cp -r /root/client/Archipel/ /var/www/

/etc/init.d/apache2 start

 

NOTA: Para bajarse el JavaScript se conecta al 80 del Apache luego el JavaScript conecta directamente al 5280 de Ejabberd sin necesidad de pasar por el apache, si se conecta a una vm por VNC el JavaScript conecta directamente machine_ip:6900+X, sis estamos detrás de un NAT deberemos tenerlo en cuenta.

Además en la config del agente debemos tener en cuenta que la ip indicada debe ser resorvible desde el exterior:

vi /etc/archipel/archipel.conf

machine_ip                  = alfaexploit.com --> IP WAN resolvible desde el exterior

 

Accedemos a nuestro Archipel:

http://IP_WEBSERVER/

JabberID: [email protected]
Password: XXXXXXXXXXX
XMPP Service: http://alfaexploit.com:5280/http-bind

 

Podemos comprobar que el BOSCH del ejabberd funciona correctamente con:

curl http://alfaexploit.com:5280/http-bind
tail -f /var/log/apache2/error_archipel.log

 

En este enlace podemos seguir los pasos iniciales de configuración.

El único apartado un poco mas complejo en cuanto a configuración es la parte de red, Archipel permite configurar todos los escenarios soportados por libvirt, esta configuración se realiza en el hipervisor pero en la máquina virtual es posible indicarle una de las redes configuradas en el hipervisor o configurar directamente un bridge.


Llegados a este punto tenemos acceso total a Archipel pero mediante BOSCH, hay una tecnología mucho mas ágil llamada websocket, en teoría ejabberd la soporta pero no funciona correctamente, de todos modos dejo los pasos necesarios para testearlo:

 

Compilamos el módulo necesario:

cd /usr/src
https://github.com/superfeedr/ejabberd-websockets
cd ejabberd-websockets/trunk

 

En Gentoo tendremos que hacer un apaño antes de compilar:

cp Emakefile Emakefile.ori

vi Emakefile
{'src/mod_websocket',      [{outdir, "ebin"},{i,"/usr/lib64/erlang/lib/ejabberd-2.1.13-r1/include"},{i,"/usr/lib64/erlang/lib/ejabberd-2.1.13-r1/include/web","src"}]}.
{'src/ejabberd_xmpp_websocket',      [{outdir, "ebin"},{i,"/usr/lib64/erlang/lib/ejabberd-2.1.13-r1/include"},{i,"/usr/lib64/erlang/lib/ejabberd-2.1.13-r1/include/web","src"}]}.
{'src/ejabberd_websocket',      [{outdir, "ebin"},{i,"/usr/lib64/erlang/lib/ejabberd-2.1.13-r1/include"},{i,"/usr/lib64/erlang/lib/ejabberd-2.1.13-r1/include/web","src"}]}.

 

Compilamos e instalamos:

./build.sh
cp ebin/* /usr/lib64/erlang/lib/ejabberd-2.1.13-r1/ebin/

 

Configuramos el Ejabberd:

vi /etc/jabber/ejabberd.cfg

%%%   LISTENING PORTS
  {5280, ejabberd_websocket, [{request_handlers, [{["ws-xmpp"], mod_websocket}]}]},

%%%   MODULES
  {mod_websocket, []},

 

Reiniciamos el servicio:

/etc/init.d/ejabberd restart

 

http://IP_WEBSERVER/

JabberID: [email protected]
Password: XXXXXXXXXXX
XMPP Service: http://alfaexploit.com:5280/ws-xmpp

 

Si esta opción os a funcionado genial, en caso contrario pasamos al plan B.

 

Nos aseguramos de que Ejabberd no intente utilizar websockets:

vi /etc/jabber/ejabberd.cfg

  %%{5280, ejabberd_http, [
  %%           http_bind,
  %%           http_poll,
  %%           web_admin
  %%             ]}

  %%{mod_http_bind,[
  %%             {max_inactivity, 480}   % timeout value for the BOSH,
  %usefull for a large number of VM
  %%           ]},

/etc/init.d/ejabberd restart

 

Instalamos node-xmpp como servidor websocket:

emerge nodejs
npm install ltx underscore log4js eventpipe node-expat dns-srv tav ws node-lumberjack node-uuid ejs
cd /usr/src
git clone https://github.com/dhruvbird/node-xmpp-bosh.git
cd node-xmpp-bosh
./run-server.js &

 

http://IP_WEBSERVER/

JabberID: [email protected]
Password: XXXXXXXXXXX
XMPP Service: http://alfaexploit.com:5280/http-bind --> ws://alfaexploit.com:5280


Se pueden generar plantillas para luego desplegar vms mas rápido, también se podría clonar una vm pero se tiene que apagar primero, se tiene que hacer una config previa:

 

vi /etc/apache2/vhosts.d/01_VMCastsArchipel.conf

Listen 8088
<VirtualHost *:8088>
        ServerName vmcasts.jupiter.alfaexploit.com
        ServerAdmin [email protected]
        DocumentRoot /vm/vmcasts
        DirectoryIndex rss.xml
        ErrorLog "/var/log/apache2/error_vmcastsarchipel.log"
        CustomLog "/var/log/apache2/access_vmcastsarchipel.log" combined
        LogLevel debug

        <Directory />
            Order Deny,Allow
            Deny from all
        </Directory>

        <Directory "/vm/vmcasts">
                Options +Indexes -FollowSymLinks
                AllowOverride None
                Order Deny,Allow
                Allow from all
        </Directory>
</VirtualHost>

 

vi /etc/apache2/httpd.conf
NameVirtualHost *:80

 

vi /etc/hosts
IP_WEBSERVER   alfaexploit.com vmcasts.jupiter.alfaexploit.com

 

En Archipel en el apartado hypervisor:
VMCasts Managememt:
http://vmcasts.jupiter.alfaexploit.com:8088

 

Para generar las plantillas vamos a una vm apagada --> Appliances, esto nos generará un fichero con la metainformación y la imagen del disco en: /vm/vmcasts


NOTA: No generar el appliance con el disco de instalación configurado en la vm o se incluirá en la imagen.

 

Archipel está bugeado y cada vez que se quiere desplegar una copia del appliance hay que poner "a machete" desde donde leer la imagen:

cd /usr/src/Archipel/ArchipelAgent/archipel-agent-vmcasting/
tar czvf archipelagentvmcasting.tar.gz archipelagentvmcasting
mv archipelagentvmcasting.tar.gz /root/
cd archipelagentvmcasting

vi appliancedecompresser.py
        #package             = tarfile.open(name=self.package_path)
        package             = tarfile.open("/vm/vmcasts/AA.xvm2", "r:")

 

Para agilizar un poco podemos utilizar este pequeño "truco" en cada despliegue nuevo desde un appliance:

asd="/vm/vmcasts/AA.xvm2"
sed -i "s/package             = tarfile.open(name=self.package_path)/package             = tarfile.open("$asd", "r:")/g" appliancedecompresser.py|grep 'tarfile.open'
python -m compileall . && kill $(ps aux|grep runarchipel|grep -v grep|awk -F " " '{print$2}') && runarchipel

tail -f /var/log/archipel/archipel.log

 

Creamos una vm nueva, en Appliances, botón derecho --> Use the selected Appliance


Autor: Kr0m -- 17/04/2014 23:04:43