By mviera Apr.15.2012
In: apache
0 comments

Autenticando con certificado digital tras un proxy reverso

Hace ya algún tiempo, trabajando en Yaco Sistemas, me encontré con un contratiempo tras desplegar una aplicación web y hoy he decidido compartir con vosotros la experiencia. Así que voy a ello.

Escenario

Como apunte inicial, comenzaré diciendo que este post trata la autenticación con certificado digital x509 entre Apache y Tomcat y el escenario en el que nos movemos sería, a grandes rasgos, como el que muestra la imagen a continuación.

Read the full story

By mviera Mar.6.2012
In: gnu/linux
3 comments

Actualizando CentOS a una release concreta

CentOS Logo

Ya hacía bastante tiempo que no paraba por aquí para escribir un artículo, así que hoy me voy a tomar mi tiempo y voy a escribir acerca de CentOS.

¿Y por qué sobre CentOS? Pues resulta que hoy trabajando en Yaco Sistemas, mi compañero @sepu66 necesitaba varias máquinas virtuales con CentOS 5.6, aunque la template de la que disponía era de CentOS 5.5. Fácil, pensé, creo la máquina virtual con CentOS 5.5 y actualizo la distribución con yum update:

[root@test ~]# yum update

Y claro, pasados unos minutos actualizando paquetes, compruebo la release de la distribución y, para mi sorpresa, observo que se ha actualizado a la última release de CentOS 5, es decir, a CentOS 5.7:

[root@test ~]# cat /etc/issue
CentOS release 5.7 (Final)
Kernel \r on an \m

FAIL!, pensé (últimamente pienso mucho). Esto ya lo había yo solucionado antes, pero no lo recordaba bien. Es una de esas tareas que haces una vez en muchos meses y que al final terminas olvidando, así que por eso he decidido hacer un volcado de conocimiento en este artículo :-)

Tras un rato buscando alguna solución en internet, sin éxito por cierto, ya que todos los artículos que encontraba eran acerca de “Cómo actualizar CentOS de 5.4 a 5.5″ o “Cómo actualizar CentOS de 5.5 a 5.6″, en resumen, todos los artículos que encontraba eran actualizaciones a la release inmediatamente superior, así que se resumían en ejecutar yum update y listo… Pero mi idea era decidir yo a qué release concreta a actualizar.

Para solucionar este tema, volví a regenerar la máquina virtual con CentOS 5.5 y empecé a modificar la configuración de los repositorios.

Configurando los repositorios

En CentOS normalmente los repositorios se encuentran configurados en ficheros que terminan en .repo en el directorio /etc/yum.repos.d/. En mi caso los repositorios configurados por defecto se encuentran en el fichero /etc/yum.repos.d/CentOS-Base.repo, así que lo primero que hice fue editar dicho fichero y deshabilitar los repositorios por defecto, añadiendo la siguiente linea en cada parte de configuración de cada repositorio:

enabled=0

Dicha linea indica a yum que el repositorio en cuestión se encuentra deshabilitado y no queremos que se utilice. Otra forma de deshabilitar los repositorios por defecto sería eliminando el fichero /etc/yum.repos.d/CentOS-Base.repo, pero no me parece un solución muy elegante.

Hecho esto, creé un nuevo fichero llamado /etc/yum.repos.d/CentOS-Vault.repo en el que añadí lo siguiente:

#---- Packages previously released as 5.6, and its updates
[C5.6-base]
name=CentOS-5.6 - Base
baseurl=http://vault.centos.org/5.6/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
enabled=1

[C5.6-updates]
name=CentOS-5.6 - Updates
baseurl=http://vault.centos.org/5.6/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
enabled=1

[C5.6-extras]
name=CentOS-5.6 - Extras
baseurl=http://vault.centos.org/5.6/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
enabled=1

¿Dónde está el truco? El secreto se encuentra en el dominio utilizado en la URL, vault.centos.org que se trata de un sitio perteneciente a CentOS donde se pueden encontrar los paquetes de releases antiguas de CentOS. Destacar como segundo truco que he fijado la versión de la release a 5.6 en la URL, por tanto esta distribución no pasará a una release posterior.

Importante también marcar los repositorios como activos especificando:

enabled=1

Listando los repositorios disponibles

Una vez configurado los repositorios a utilizar, podemos listarlos ejecutando yum repolist:

[root@test ~]# yum repolist
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
repo id                                                                     repo name
C5.6-base                                                                   CentOS-5.6 - Base
C5.6-centosplus                                                             CentOS-5.6 - Plus
C5.6-extras                                                                 CentOS-5.6 - Extras
C5.6-updates                                                                CentOS-5.6 - Updates

Actualizando la distribución

Hecho esto, ya sólo nos queda forzar la actualización del sistema completo:

[root@test ~]# yum update

y pasados unos minutos actualizando los paquetes del sistema, deberíamos tener nuestra distribución en la versión deseada, en mi caso, CentOS 5.6:

[root@test ~]# cat /etc/issue
CentOS release 5.6 (Final)
Kernel \r on an \m

Espero que os sea de utilidad, a mi seguro que no se me vuelve a olvidar :-D
Un saludo!

By mviera Sep.2.2011
In: gunicorn
2 comments

Desplegando Trac con Gunicorn

En mi anterior post hablé sobre Gunicorn, un servidor HTTP WSGI para Python, y terminé diciendo que en el próximo articulo iba a explicar cómo desplegar Trac con Gunicorn y como lo prometido es deuda, vamos a ello…

Preparando el entorno

Antes de nada, vamos a crear un directorio de trabajo, donde se alojará todo. Se me ocurre llamarlo testing-gunicorn:

$ mkdir testing-gunicorn
$ cd testing-gunicorn

Antes de comenzar a instalar Trac y Gunicorn, vamos a crear un virtualenv en el directorio testing-gunicorn, dentro del cual instalaremos todos los modulos de Python necesarios:

$ virtualenv --no-site-packages --distribute .

y activamos el virtualenv:

$ source bin/activate

Instalando Trac y Gunicorn

La instalación es realmente sencilla. Al igual que para instalar cualquier otro módulo de Python, utilizaremos easy_install o pip. Yo opto por utilizar pip, así que ejecutamos las siguientes instrucciones:

$ pip install Trac
$ pip install gunicorn

Una vez hecho esto, deberemos tener instalado Trac y Gunicorn dentro de nuestro virtualenv, el mismo que tenemos activado.

Para comprobar que la instalación se ha realizado correctamente, abriremos una shell de Python e importaremos los dos módulos instalados:

$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import trac
>>> import gunicorn
>>>

Esto quiere decir que la instalación se ha realizado correctamente. En caso contrario, obtendriamos un error al intentar importar el módulo, y se mostraría un error como el siguiente:

>>> import trac
Traceback (most recent call last):
  File "", line 1, in
ImportError: No module named trac

Pero no es nuestro caso, asi que sigamos adelante :-)

Creando un Trac de ejemplo

Tenemos Trac instalado, así que el siguiente paso será crear una instancia de Trac.
Crearemos un directorio llamado ‘projects’ donde crearemos nuestras instancias de Trac:

$ mkdir projects

y finalmente crearemos la instancia de Trac llamada demo, haciendo uso de la utilidad trac-admin:

$ trac-admin projects/demo initenv demo sqlite:db/trac.db

A modo de resumen, le hemos especificado a trac-admin que cree una instancia de Trac en el directorio projects/demo con la opción initenv, cuyo nombre es “demo” y siendo la base de datos de tipo sqlite, que se encontrará en db/trac.db.

Hecho esto, tendremos nuestra instancia de Trac creada con una estructura como la siguiente:

projects/
└── demo
    ├── attachments
    ├── conf
    │   ├── trac.ini
    │   └── trac.ini.sample
    ├── db
    │   └── trac.db
    ├── htdocs
    ├── log
    ├── plugins
    ├── README
    ├── templates
    │   └── site.html.sample
    └── VERSION

Configurando Gunicorn

Como comenté en el anterior post, la configuración de Gunicorn la realizaremos creando un fichero Python.

Nuestro fichero de configuración se llamará trac_launcher.py y su contenido debe ser el siguiente:

#!/usr/bin/env python
import sys
import os
import trac.web.main

sys.stdout = sys.stderr
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

os.environ['TRAC_ENV_PARENT_DIR'] = os.path.join(PROJECT_ROOT,'projects')
os.environ['PYTHON_EGG_CACHE'] = os.path.join(PROJECT_ROOT, '.egg-cache')
application = trac.web.main.dispatch_request

Básicamente el fichero de configuración está compuesto por:

  1. Importaciones de los módulos sys, os y trac.web.main.
  2. Creación de dos variables de entorno:
    • TRAC_ENV_PARENT_DIR: directorio donde se alojan las instancias de Trac.
    • PYTHON_EGG_CACHE: directorio de caché de los huevos de Python.
  3. Instancia de la funcion trac.web.main.dispatch_request en la variable application.

Antes de seguir hagamos un breve repaso:

  • Nos encontramos en el directorio testing-gunicorn.
  • Tenemos nuestra instancia de Trac en projects/demo.
  • Hemos creado en el directorio actual el fichero de configuración para Gunicorn, llamado trac_launcher.py.

El siguiente paso será ejecutar Gunicorn!

Ejecutando Gunicorn

Tan fácil como ejecutar la siguiente instrucción:

$ gunicorn trac_launcher:application

¡Guay! Ya deberíamos tener nuestro proyecto Trac accesible en http://localhost:8000 :-D

Por defecto Gunicorn arranca un solo worker, pero podemos indicarle que arranque más de uno, un número máximo de peticiones por worker y un fichero de log, por ejemplo:

$ gunicorn trac_launcher:application \
--workers 2 \
--worker-connections 100 \
--log-file gunicorn.log

Como hemos podido observar, Gunicorn abre por defecto el puerto 8000 en nuestro sistema, pero si por el contrario la comunicación la queremos hacer a través de un socket, deberemos indicarle la opción --bind unix:///home/mviera/testing-gunicorn/gunicorn.sock.

Por último y para terminar el despliegue, deberíamos instalar un servidor web que actuara de proxy, ya sea hacia HOST:PUERTO o hacia el fichero de socket.

Y eso esto todo amig@s! Espero que os haya gustado y gracias por leerme!

Un saludo!

By mviera Sep.1.2011
In: gunicorn
4 comments

Gunicorn

Hace no mucho que empecé a escuchar sobre Gunicorn, creo que allá por Marzo cuando Lorenzo Gil se encontraba en la PyCon 2011, pero no me había propuesto probarlo hasta hace unos días. Pero bueno, empecemos por el principio…

¿Qué es Gunicorn?

Gunicorn, también conocido como Green Unicorn (Unicornio Verde), es un servidor WSGI HTTP para Python. Es un pre-fork del proyecto Unicorn de Ruby.
Gunicorn es compatible con varios web frameworks, soporta WSGI, Django y Paster de forma nativa; consume pocos recursos en ejecución y es bastante rápido.

Como he comentado en el párrafo anterior, soporta nativamente WSGI, Django y Paster; administra los workers de forma automática, permite establecer hooks para hacerlo más extensible, compatible con Python 2.5 o superior.

Instalando Gunicorn

Su instalación es realmente sencilla, justo como cualquier otro módulo de Python.

$ pip install gunicorn

o si lo preferimos, podemos obtener el código con git e instalarlo como cualquier otra aplicación en Python.

$ git clone git://github.com/benoitc/gunicorn.git
$ cd gunicorn
$ python setup.py install

Una vez instalado Gunicorn tendremos a nuestra disposición tres comandos con los que servir diferentes web frameworks.

Ejecutando Gunicorn

Los comandos disponibles en Gunicorn son:

  • gunicorn: utilizado para servir aplicaciones WSGI.
  • gunicorn_django: utilizado para servir aplicaciones Django.
  • gunicorn_paster: para frameworks compatibles con Paster como Pylons, TurboGears 2, …

En este post me centraré en el comando gunicorn pero podeis encontrar más información de cada uno de ellos en la documentación oficial de Gunicorn.

Configurando Gunicorn

La configuración de Gunicorn también es muy sencilla, básicamente consiste en un fichero Python que tenga permisos de lectura en el sistema de ficheros, excepto que nuestra aplicación haya sido desarrollada utilizando Paster, en este caso haremos uso de un fichero INI.

Su sintaxis de uso es:

$ gunicorn [OPTIONS] APP_MODULE

Donde APP_MODULE está compuesto por $(MODULE_NAME):$(VARIABLE_NAME). Un ejemplo de uso sería el siguiente:

$ gunicorn --workers 2 prueba:aplicacion

Gunicorn buscará el módulo, es decir, el fichero prueba.py, y el nombre de la variable (aplicacion) debe hacer referencia a una función, normalmente a la función main de nuestra aplicación, que debe encontrarse especificada en el módulo.

El comando gunicorn ofrece una extensa lista de opciones para configurar su comportamiento, pero las que he utilizado y que me han parecido más interesantes son:

  • --config FILE: ruta hacia el fichero de configuración.
  • --bind ADDRESS: es posible especificar tanto HOST:PUERTO como la ruta a un socket con unix:RUTA_SOCKET.
    Ejemplo: --bind unix:///home/mviera/gunicorn/gunicorn.sock
  • --workers INT: número de procesos workers que se arrancarán para servir las peticiones.
  • --max-requests INT: número máximo de peticiones que servirá un worker antes de ser reiniciado.
  • --debug: activa el debug en el servidor.
  • --log-file: fichero de log.

Un ejemplo de ejecución sería:

$ gunicorn modulo:application --workers 2 \
--bind unix:///home/mviera/gunicorn/gunicorn.sock \
--max-requets 1000 --log-file /home/mviera/gunicorn/gunicorn.log

Podeis consultar el resto de opciones en la documentación de configuración de Gunicorn.

Por último y para terminar con el despliegue, una vez que tengamos a Gunicorn sirviendo nuestra aplicación lo correcto sería instalar un servidor web que actúe como proxy HTTP hacia nuestra aplicación, yo como siempre recomiendo utilizar Nginx :-)

Y hasta aquí lo que he aprendido sobre Gunicorn, un breve resumen de la documentación oficial.

Conclusiones

Gunicorn me ha sorprendido no solo por su fácil instalación, a diferencia de uWSGI que necesita ser compilado; sino también por su fácil configuración y uso.

Como dije al principio, cuenta con una serie de hooks que permite ejecutar código Python en los diferentes puntos de ejecución: on_start, when_ready, on_reload, pre_fork, post_fork, etc. Esto también me ha gustado mucho, aunque no los he llegado a probar.

La verdad es que Gunicorn me ha dejado con un muy buen sabor de boca aunque no he llegado a probarlo en un entorno real de producción para ver cómo se comporta. De momento seguiré con uWSGI hasta que tenga la ocasión de utilizar Gunicorn ;-)

Un saludo.

PD: En el próximo post explicaré cómo desplegar Trac utilizando Gunicorn!

By mviera Aug.23.2011
In: python
2 comments

Automatizando con Tox

Hace unos días me encontré con Tox y realmente me llamó la atención, pero…

¿Qué es Tox?

Tox es un gestor de virtualenvs y una herramienta para realizar tests en linea de comandos. Según su documentación se puede utilizar para:

  • Probar que tu paquete se instala correctamente con diferentes versiones de Python.
  • Ejecutar los tests de tu proyecto en cada uno de los entornos.
  • Integración Continua (CI = Continuous Integration).

No me ha quedado claro, ¿Cual es el objetivo?

El objetivo de tox es automatizar el arte de empaquetado, testeo e instalación de software Python ya sea desde tu consola o desde tu servidor de CI (Integración Continua).

Lo quiero probar, ¿cómo lo instalo?

Es muy fácil, solamente se necesita ejecutar la siguiente instrucción:

pip install tox

Instalado, pero ¿cómo hago una primera prueba?

Se necesita crear un fichero llamado tox.ini que debe estar en el mismo directorio quesetup.py cuyo contenido puede ser algo como:

[tox]
envlist = py26,py27
[testenv]
deps =
    unittest2
    pytest
commands=python bin/test

¿Y ahora qué hago?

Una vez creado el fichero tox.ini solamente será necesario ejecutar:

tox

Será entonces cuando tox comienze a:

  1. empaquetar las fuentes del proyecto en un fichero zip
  2. creará un virtualenv por cada uno de los interpretes especificados, en este caso un virtualenv para Python-2.6 y otro para Python-2.7, cuyos nombres serán py26 y py27 respectivamente.
  3. instalará las dependencias especificadas (en este caso de ejemplo,unittest2 y pytest).
  4. por último se ejecutarán los comandos especificados, en nuestro ejemplo solamente uno, python bin/test.
Importante: los intérpretes de Python deben estar previamente instalados en el sistema.tox no instala ningún intérprete de Python y en caso de no encontrar alguno de los especificados, informará de ello mostrando un error en linea de comandos.
Si ejecutamos tox por segunda vez podremos comprobar que la ejecución durará mucho menos puesto que no necesita resolver de nuevo las dependencias.

¿Y si sólo quiero ejecutar los tests en uno de los intérpretes?

Bastaría con ejecutar la siguiente instrucción:

tox -e py27

¿Dónde se almacena el resultado de la ejecución de tox?

tox crea un directorio oculto llamado .tox que tiene la siguiente estructura:

.tox
├── dist
├── _download
├── log
└── py27
    ├── bin
    ├── include
    ├── lib
    └── log
  • dist: directorio donde se almacenan las fuentes del proyecto comprimidas en formato zip.
  • _download: directorio de descarga de todas las dependencias de Python.
  • log: directorio donde se almacenan los ficheros de log de la ejecución.
  • py27: directorio del virtualenv creado para instalar el proyecto utilizando python2.7.

… y eso es todo amig@s! Podéis aprender más acerca de tox consultando la documentación oficial en http://tox.readthedocs.org
 

Un saludo!
 

By mviera Aug.21.2011
In: osx
2 comments

Cambiar contraseñas en OS X sin un CD de OS X

Hace no mucho una amiga que tiene un Macbook me comentó que por alguna extraña razón no podía acceder a su cuenta de usuario. Ella aseguraba no haber cambiado la contraseña y que la que estaba introduciendo era la contraseña correcta. Y sí, el teclado respondía al layout en español, y el bloqueo de mayúsculas no estaba activado. Me comentaba que tenía material gráfico de mucha importancia y que no se podía perder, vamos, lo de siempre :-D. Solo existía su usuario en el sistema, y por lo tanto el único usuario administrador.

Fue entonces cuando busqué un poco por internet, y los pasos a seguir son los siguientes:

  1. Reiniciar el sistema.
  2. Mantener pulsado la tecla Command en Apple (⌘) + s antes de escuchar el sonido inicial de arranque.
  3. Deberá aparecer una shell en la que tendremos privilegios de root y desde la cual ejecutaremos las siguientes instrucciones:
  4. # mount -uw /
    # rm /var/db/.AppleSetupDone
    # shutdown -h now
  5. Después del reinicio del sistema aparecerá de nuevo el video de bienvenida y la posibilidad de crear un nuevo usuario administrador tal y como cuando sacamos nuestro Mac de la caja por primera vez.
  6. Creado el nuevo usuario administrador y habiendo hecho login con él podremos acceder a las Preferencias del Sistema > Cuentas y cambiar la contraseña del anterior usuario administrador.

Parece ser que tras completar los primeros pasos en OS X, se crea el fichero /var/db/.AppleSetupDone en el sistema. Es un fichero vacío, no contiene ninguna configuración, así que imagino que durante el arranque se comprueba si existe este fichero, y si existe es que el sistema ya ha sido configurado, si no, se muestra la bienvenida a OS X.

Espero que os sea útil, y tened cuidado con el lado oscuro ;-)

Un saludo.

By mviera Aug.20.2011
In: Uncategorized
4 comments

Retomando el blog

Es muy probable que nadie haya echado en falta mi blog, pero sí, llevo desde febrero si escribir absolutamente nada en él, asi que -10 para mí :-(

Supongo que no hay excusa pero, si es cierto que he estado trabajando bastante estos meses atrás y claro, después de pasar 10 horas delante de un ordenador, a uno no le quedan muchas fuerzas al llegar a casa para sentarse a elaborar un artículo para el blog. Mal hecho por mi parte, ya que cuando escribo en el blog me sienta bien, me siento útil, por lo menos por el hecho de intentar compartir conocimiento.

Imagino que tras unas vacaciones, de las cuales ya hablaré cuando me encargue de esas 1397 fotografías, es como volver a retomar los propósitos, como cada año nuevo.

Así que dicho esto, voy a seguir intentando arañar horas a mis días para seguir escribiendo y compartiendo con todos vosotr@s.

Un saludo y gracias por leerme!

By mviera Feb.1.2011
In: buildout, software libre, trac, yaco
3 comments

EasyTrac, un despliegue automatizado de Trac.

Como ya comenté en posts anteriores, en Yaco Sistemas trabajamos a diario con Trac, todas nuestras tareas están en Trac, incluyendo documentación de proyectos, etc; en Yaco Sistemas no eres nadie si no creas una wiki ;-)

Eso está muy bien, ¿pero qué es easyTrac?

EasyTrac es un instalador basado en zc.buildout que despliega un entorno de Trac de forma automatizada incluyendo dependencias necesarias.

Este instalador no solo puede ser utilizado para desarrollo sino que también podría utilizarse en un sistema de producción ya que los proyectos de Trac se despliegan bajo Nginx y uWSGI, con lo que tendremos un sistema bastante rápido, estable y liviano en nuestro sistema.

Si es cierto que para poder compilar Nginx y uWSGI, es necesario que se encuentren ciertas librerias de desarrollo en el sistema, por lo que deberemos tener instalados los siguientes paquetes en nuestro sistema:

  • libpcre3-dev
  • libssl-dev
  • libxml2-dev
  • libxslt-dev
  • libsqlite3-dev
  • libzzip-dev
  • libapr1-dev
  • libaprutil1-dev
  • python-dev

Me parece correcto… ¿pero de dónde me lo descargo?

Puedes descargarlo de forma comprimida tanto en formato zip como en formato tar.gz.

O si lo prefieres, puedes hacer un clone con Git de mi repositorio en Github ejecutando lo siguiente:

$ git clone git://github.com/mviera/easyTrac

Vale, ya lo tengo ¿y ahora cómo lo instalo?

EasyTrac se puede instalar tanto como root como con cualquier usuario sin privilegios, ya que la instalación no interferirá para nada en nuestro sistema. Personalmente, prefiero instalar con un usuario sin privilegios.

El instalador de easyTrac funciona sin tener que hacer ninguna modificación en la configuración, pero si quieres personalizar la configuración, puedes editar el fichero buildout.cfg y modificar alguno de los siguientes parámetros:

  • nginx-http-port: puerto utilizado por Nginx para escuchar las peticiones vía http.
  • nginx-https-port: puerto a través del cual Nginx escuchará las peticiones vía https (en caso de que quieras usar https).
  • supervisor-http-port: puerto utilizado por Supervisor.
  • host: IP del host o FQDN (Fully Qualified Domain Name)
  • socket-directory: directorio donde se almacenarán los sockets.
  • pid-directory: directorio donde se alojarán los ficheros pid.
  • log-directory: directorio de logs.
  • trac-projects-directory: directorio donde se crearán los proyectos de Trac. Por defecto este directorio es <installdir>/opt/trac/.
  • svn-repository-directory: directorio donde se crearán los repositorios de código SVN. Por defecto, este directorio es <installdir>/opt/svn/.

Una vez instaladas las anteriores dependencias, y configurados los parámetros de configuración, en caso de que quisieras personalizarlos, podemos seguir con la instalación, así que ejecutaremos lo siguiente:

$ python bootstrap.py

Con esto prepararemos el entorno y una vez hecho, podremos lanzar la instalación ejecutando lo siguiente:

$ ./bin/buildout

Comenzará el proceso de compilado de Nginx y uWSGI; y la instalación de los módulos de Python necesarios. Además, easyTrac compila Subversion e instala los bindings necesarios para que Trac pueda enlazarse con repositorios de código SVN.

He ido a por un café y al volver ya estaba instalado ¿ahora qué hago?

EasyTrac incluye la instalación de Supervisor. Pero ¿qué es Supervisor? Es un sistema de control de procesos que nos va a permitir arrancar, parar y reiniciar cada uno de nuestros servicios. En easyTrac tendremos dos servicios: Nginx y uWSGI.

La sintaxis de uso de Supervisor es la siguiente:

$ ./bin/supervisorctl

Por lo tanto si quisiéramos iniciar el servicio Nginx, ejecutaríamos lo siguiente:

$ ./bin/supervisorctl start nginx

En caso de querer pararlo, ejecutaremos:

$ ./bin/supervisorctl stop nginx

Y si quisiéramos reiniciarlo:

$ ./bin/supervisorctl restart nginx

Supervisor incluye una palabra especial llamada all que hace referencia a todos los servicios configurados en supervisor. Con ella podremos controlar todos los servicios al mismo tiempo. Por ejemplo, si quisiéramos reiniciar todos los servicios, ejecutaríamos lo siguiente:

$ ./bin/supervisorct restart all

Pero esto no es todo, es que además Supervisor, por si fuera poco, incluye una interfaz web desde la que podemos controlar nuestros servicios. Podremos acceder a ella accediendo a

http://localhost:9000

Por defecto, el usuario es admin y la contraseña es admin. (nótese el punto al final de admin). Es posible cambiar estos datos editando la parte [supervisor] en el fichero buildout.cfg y volveremos a ejecutar la instrucción ./bin/buildout

Ya tenemos nuestro entorno listo y accederemos a él a través de

http://localhost:8080

¡Qué bien! ¿y ahora cómo creo un Trac?

Tranquilos, la creación de un proyecto Trac es muy sencilla. Utilizaremos el binario trac-admin creado por el instalador, y que se encuentra en el directorio bin/.

Crearemos un proyecto llamado demo, por lo que ejecutaremos lo siguiente:

$ ./bin/trac-admin opt/trac/demo initenv demo sqlite:db/trac.db

Y ya que estamos, vamos a crear un repositorio SVN con el mismo nombre. Para ello utilizaremos el binario llamado svnadmin que podremos encontrar también en el directorio bin/.

$ ./bin/svnadmin create opt/svn/demo

Fiuf! ahora solo falta que pudiera hacer backups de mis Tracs

Aunque no es una solución feténica, easyTrac cuenta con un comando backup con el que podremos comprimir nuestros proyectos y guardarlos en otra localización. Para ello, simplemente ejecutaremos la siguiente instrucción:

$ ./bin/backup

y todos los proyectos Trac serán comprimidos y guardados en un directorio llamado backups/.

Vale, tengo backups, quiero restaurarlos ¿cómo lo hago?

Tan simple como ejecutar lo siguiente:

$ ./bin/restore backups/backup-file.tar.gz

y todos los tracs serán restaurados automáticamente en el directorio, por defecto, opt/trac/.

No me convence. Quiero desinstalarlo.

Solamente es necesario parar todos los servicios:

$ ./bin/supervisorctl shutdown

y borrar el directorio de instalación:

$ rm -rf easyTrac

And that’s all folks!!! ;-)

Un saludo!

By mviera Jan.27.2011
In: gnu/linux, yaco
3 comments

Crontab

Hoy trabajando en Yaco Sistemas he aprendido algo nuevo sobre cron. Seguramente muchos de los que os moveis entre GNU/Linux y similares, conoceréis el demonio cron.

Cron es un planificador de tareas que nos permite ejecutar una tarea en un momento determinado en el tiempo. La sintaxis para configurar una tarea cron es la siguiente:

.---------------- minuto (0 - 59)
|  .------------- hora (0 - 23)
|  |  .---------- día del mes (1 - 31)
|  |  |  .------- mes (1 - 12)
|  |  |  |  .---- día de la semana (0 - 6) (Domingo=0)
|  |  |  |  |
*  *  *  *  *  comando para ser ejecutado

De esta forma, imaginad que queremos apagar nuestro ordenador los sábados a las 21:30h, configuraríamos una tarea cron de la siguiente forma:

30 21 * * 6 /sbin/shutdown -h now

Podemos planificar tareas para un usuario utilizando el comando crontab:
crontab -l Lista las tareas cron para el usuario actual.
crontab -e Permite configurar una tarea cron para el usuario actual. Se abrirá el editor de texto configurado por defecto en el sistema.
crontab -r Elimina las tareas cron configuradas en el usuario actual.
crontab -v Muestra la última vez que se editó crontab del usuario actual.

La verdad es que no parece una sintaxis muy complicada pero a mi, personalmente, siempre se me olvida.

Como os decía al principio, hoy he descubierto los horarios predefinidos en crontab gracias a ant30. Estos horarios predefinidos son unos valores que se pueden usar para sustituir la sintaxis de las expresiones anteriores. Estos valores predefinidos son:

@yearly Se ejecuta una vez al año. Equivalente a 0 0 1 1 *
@annually (igual que @yearly). Equivalente a 0 0 1 1 *
@monthly Se ejecuta una vez al mes. Equivalente a 0 0 1 * *
@weekly Se ejecuta una vez a la semana. Equivalente a 0 0 * * 0
@daily Se ejecuta una vez al día. Equivalente a 0 0 * * *
@midnight (igual que @daily). Equivalente a 0 0 * * *
@hourly Se ejecuta una vez cada hora. Equivalente a 0 * * * *
@reboot Se ejecuta en el arranque y al reiniciar.

El que yo he utilizado hoy ha sido @reboot que me permite ejecutar un comando cuando arranca el sistema. En mi caso quería que cada vez que se arranque el sistema, se iniciara un servicio desplegado con el usuario en cuestión. Gracias a @reboot no tengo que crear un script en /etc/init.d/ y activarlo en el arranque ;-)

Un saludo!

By mviera Jan.22.2011
In: asterisk, software libre, voip
3 comments

Configurando los clientes SIP

Bueno, vamos a empezar por el principio. Deberemos tener presente el diagrama de red que presenté en el anterior post y por eso lo incluyo también en este.

Para poder utilizar el canal SIP lo primero que tenemos que hacer es configurar las cuentas SIP, utilizadas por nuestros dispositivos VoIP(softphones, tfnos digital y analógico y gateway) para registrarse en nuestra centralita Asterisk. Pero…

¿Qué es SIP?

Session Initiation Protocol o Protocolo de Inicio de Sesión. Es un protocolo desarrollador por el grupo MMUSIC del IETF con el fin de ser el estandar para la iniciación, modificación y finalización de sesiones interactivas de usuario donde interviene audio, video, mensajería instantanea, juegos en linea y realidad virtual. SIP es uno de los protocolos de señalización para voz sobre IP, junto con otros como H.323 e IAX2.

sip.conf

El fichero de configuración del canal sip se encuentra en /etc/asterisk/sip.conf y por tanto será donde configuremos las cuentas SIP. Su formato es similar al de los ficheros .ini; por lo que se encuentra dividido en secciones conocidas en Asterisk como contextos. En el fichero sip.conf hay un contexto predefinido, se llama [general]:

En el contexto [general] definiremos parámetros que se aplicarán en todos los contextos posteriores. Algunos de los parámetros generales del canal SIP son:

  • port: es el puerto que utilizará Asterisk para escuchar conexiones SIP entrantes. El puerto SIP por defecto es el 5060.
  • binaddr: interfaz de red que utilizará Asterisk para atender las conexiones SIP entrantes. El valor por defecto es 0.0.0.0, es decir, escucha en todas las interfaces de red disponibles.
  • context: contexto que se aplica a las llamadas entrantes. Se aplica cuando una cuenta SIP no tiene definido un contexto.
  • videosupport: soporte de video en SIP. Permite los valores ‘yes’ o ‘no’.
  • language: lenguaje utilizado por defecto para todos los clientes SIP.
  • allow: especificamos los códecs de sonido que vamos a utilizar. Permite valores como ‘all’, ‘alaw’, ‘ulaw’, ‘gsm’, etc.
  • disallow: códecs de audio que no vamos a permitir. Cuando vamos a restringir los códecs de audio, lo mejor es siempre prohibirlos todos (disallow=all) y luego permitir aquellos que queramos.
  • nat: habilitamos o deshabilitamos el soporte de nat para la extensión.

Un ejemplo para el contexto [general] en /etc/asterisk/sip.conf podría ser la siguiente:

[general]
port=5060
bindaddr=0.0.0.0
context=normal
videosupport=no
language=es
disallow=all
allow=alaw,gsm

Definiendo los clientes SIP

Como he comentado anteriormente, antes de que un cliente SIP pueda enviar o recibir llamadas a través de Asterisk, debe ser declarado y configurado en el fichero /etc/asterisk/sip.conf. Cada cliente SIP se configurará como si de otro contexto / sección se tratase, y podemos especificar varios parámetros. Hasta ahora los que he utilizado han sido los siguientes:

  • type: define la clase de conexión que tendrá el cliente. Hay tres tipos de clientes SIP:
    1. peer: solo puede recibir llamadas.
    2. user: solo puede realizar llamadas.
    3. friend: puede recibir y realizar llamadas.
  • callerid: es el identificador del cliente, es decir, el nombre que aparecerá cuando se realice una llamada.
  • username: usuario con el que nos conectaremos al servidor Asterisk.
  • secret: contraseña con la que se realizará la autenticación en Asterisk junto con el username.
  • context: contexto asociado al cliente en el dialplan de Asterisk, es decir, contexto que se aplicará en el fichero extensions.conf del cual hablaremos más adelante.
  • dtmfmode: Dual-Tone Multi-Frequecy (DTMF) se refiere a la marcación por tonos. Normalmente le especifico que use el estandar rfc2833.
  • qualify: si se establece a ‘yes’ podremos monitorizar la extensión. Esta configuración no es muy recomendable cuando tenemos muchas extensiones.

Bien! Ya tenemos lo suficiente como para empezar a registrar cada uno de los clientes SIP :-) De esta forma, para registrar el teléfono digital cuya extensión es 1001 tendremos que añadir la siguiente configuración al fichero /etc/asterisk/sip.conf:

[1001]
callerid=digital
username=1001
secret=1001
type=friend
host=dynamic
context=normal
qualify=yes
pickupgroup=1
limitonpeers=yes
call-limit=4
dtmfmode=rfc2833
nat=yes

Como una breve anotación tengo que decir que en la cabecera de la sección, en este caso [1001], podemos poner cualquier cadena, creo que sin espacios, pero yo opto por poner el número de la extensión, me es más cómodo al leer la configuración.

Una que hemos configurado un cliente, los demás son coser y cantar. Vamos a registrar un nuevo cliente SIP, por ejemplo, mi portatil cuyo username es mviera y su extensión será 1003. La configuración en sip.conf sería la siguiente:

[1003]
callerid=mviera
username=1003
secret=1003
type=friend
host=dynamic
context=normal
qualify=yes
pickupgroup=1
limitonpeers=yes
call-limit=4
dtmfmode=rfc2833
nat=yes

Fácil ¿no? Pero ¿no os resulta esta última configuración un poco redundante? Algunos ya se habrán dado cuenta. En realidad esta última configuración es igual que la anterior, solamente cambian los parámetros callerid, username y secret. ¿Cierto?

Para ello, Asterisk en su últimas versiones permite el uso de máscaras. Esta funcionalidad nos permite crear una sección “padre” donde configuraremos todos los parámetros comunes. De esta forma podremos “heredar” parte de la configuración, pudiendo sobreescribir o incluir nuevos parámetros que nos sean necesarios. Utilizaremos (!) junto al nombre de la sección, para especificar que una sección actuará como una máscara. Ejemplo: [nombre_seccion](!).

Ya que sabemos sobre la existencia de las máscaras en Asterisk, vamos a modificar la configuración actual en /etc/asterisk/sip.conf. Crearemos una sección [normal] con los parámetros comunes y las extensiones 1001 y 1003 “heredarán” de esta sección.

[normal](!)
type=friend
host=dynamic
context=normal
qualify=yes
pickupgroup=1
limitonpeers=yes
call-limit=4
dtmfmode=rfc2833
nat=yes

Para especificar que una sección “hereda” de otra que actúa como máscara especificaremos el nombre de la máscara a continuación del nombre de la sección, es decir, de la siguiente forma: [nombre_seccion](nombre_mascara). Por lo que la configuración de las extensiones 1001 y 1003 se reduciría a lo siguiente:

[1001](normal)
callerid=digital
username=1001
secret=1001

[1003](normal)
callerid=mviera
username=1003
secret=1003

¿Guay no? Ahora solo nos queda reiniciar el servicio Asterisk

# /etc/init.d/asterisk restart

Nota: cuidado al reiniciar el servicio Asterisk cuando modifiquemos la configuración. Si utilizamos restart todas las llamadas activas se cortarán. Asi que mejor utilizad reload ;-)

La configuración del resto de extensiones es similar a las anteriores, aun así os dejo el enlace al fichero sip.conf.

Ojo! Todavía no podemos hacer llamadas. Hasta ahora solo hemos configurado los clientes que podrán conectarse a Asterisk, lo próximo será configurar el plan de marcado o dialplan. Pero esto ya es tema para otro post ;-)

Un saludo!