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