viernes, 20 de abril de 2012

Scrum I: La base

Scrum es un framework para la gestión y desarrollo de proyectos software mediante un enfoque iterativo e incremental. El objetivo de Scrum es poder resolver problemas complejos de manera productiva y creativa, creando un producto con la mayor calidad posible. Al ser un proceso con iteraciones de corta duración (como máximo un mes) el feedback obtenido del cliente es constante y la evolución es mas cercana a lo que desea el cliente.

Scrum esta compuesto de cinco elementos: equipo, roles, eventos, artefactos y reglas; siendo cada uno de ellos esencial para su funcionamiento. Estos elementos se cubrirán en detalle en otros articulos.

Hay tres pilares que hay que tener siempre en cuenta a la hora de trabajar con Scrum: transparencia, inspección y adaptación.

Transparencia
Los aspectos importantes del proyecto deben ser visibles para todo el entorno, usando un lenguaje común y bien definido asegurándonos que todos entienden lo mismo por el mismo termino.

Un clásico ¿Cuando algo esta terminado? Cada persona puede dar una respuesta diferente a esa pregunta.

Lo que se pretende con la transparencia es saber en todo momento en que punto nos encontramos con nuestro proyecto y hacia donde vamos.

Inspección
Sino tenemos transparencia llevar a cabo una inspección seria una tarea extremadamente tediosa, improductiva y seria realmente difícil evaluar la situación actual. Por eso al tener un proceso transparente facilita enormemente la inspección de nuestra situación actual y de como vamos avanzando hacia nuestro objetivo.

La inspecciones deben realizarse con frecuenta pero sin llegar al punto de que obstruya el trabajo. Las inspecciones van de la mano con las adaptaciones, en el siguiente punto se explicara como ponerlas en practica.

Adaptación
Luego de una inspección, los errores o desviaciones detectados que sobrepasen los limites de aceptación deben solucionarse.  Los ajustes deben hacerse cuanto antes mejor, minimizando así el grado de desviación, la cantidad de errores actuales, y se evita el arrastre de errores; todo esto ayuda a mantener la planificación y el coste inicial.

Formalmente Scrum define cuatro puntos de inspección y adaptación:
  • Sprint Planning
  • Daily Scrum
  • Sprint Review
  • Sprint Retrospective

miércoles, 18 de abril de 2012

Protocolos de arranque y configuración

Address Resolution Protocol
Primero que nada aclara que el protocolo de arranque y configuración seria RARP, pero es mucho mas claro explicar ARP para entender RARP, ya que es su caso inverso.

Address Resolution Protocol o ARP, es un protocolo que partiendo de una dirección de un protocolo de nivel superior (TCP, FTP, TELNET, etc) nos permite obtener la dirección Ethernet de un dispositivo.

Generación de paquetes ARP
Supongamos que trabajamos con el protocolo IP a nivel de red. Al enviar un mensaje desde el host A al host B, solo conocemos la direccion IP de la maquina de destino, pero a nivel de enlace el paquete es encapsulado en una trama Ethernet, por lo que sera necesario saber la dirección Ethernet de nuestra maquina destino (en caso de estar en la misma red) o de la maquina a través de la cual se hará el enrutamiento. Este proceso se hace media broadcasting, al ser un procedimiento muy costoso cada cliente mantiene una tabla de correspondencia con con los pares IP-Ethernet.

Recepción de paquetes ARP 
Como se dijo anteriormente cuando un terminal necesita determinar la dirección Ethernet de una maquina,  lo hará mediante un broadcast. Cuando una petición de resolución llega a un cliente, primero se actualiza la tabla de correspondencia (para evitar futuros broadcast) y luego se comprueba si nuestra dirección de protocolo es la buscada. Si el mensaje no va dirigido a nosotros se descarta, en caso contrario se responde al dispositivo que genero el mensaje indicándole nuestra dirección Ethernet.

Para consultar la tabla de correspondencia podemos ejecutar arp -a


Como se dijo al principio el caso inverso, es RARP, es decir conocemos la dirección física del dispositivo y queremos saber la dirección IP.


Suponiendo que tenemos que mandar un mensaje desde A (.10) a B (.20), la secuencia de mensajes de ARP es la siguiente:

  1. arp who-has 192.168.1.10 tell  192.168.1.20
  2. arp reply   192.168.1.20 is-at 00:11:22:33:44:55

Esto se puede ver perfectamente con Wireshark.

Bootstrap Protocol
Para lidiar con los problemas del broadcast limitado de RARP (255.255.255.255) surge BOOTPl objetivo de este protocolo es saber la IP de un host a partir de su dirección física. Se basa en UDP usando los puertos 67 y 68  para el servidor y el cliente respectivamente. 

El mayor problema de BOOTP es que el administrador de la red debe introducir manualmente la tabla de correspondencia IP y Ethernet, para evitar eso BOOTP evoluciono a DHCP.

Dynamic Host Configuration Protocol
DHCP se encarga de automatizar la configuración (IP, gateway, mascaras, etc) de los dispositivos. Para el cliente es como si usara BOOTP, ya que usa los mismos puertos y protocolo. La gran diferencia con los protocolos anteriores es que el servidor DHCP no tiene porque estar en la misma red, siendo necesario un agente re-transmisor. Cuando el cliente desea saber su IP genera un mensaje DHCP discover mediante broadcast, en caso de que el servidor se encuentre en la misma red le responde directamente sino el agente de retransmisión re enviara el mensaje al servidor.

  • discover: enviado desde al servidor para solicitar una IP, puede sugerir la IP deseada.
  • decline: rechaza la IP solicitada por el cliente.
  • offer: el servidor le ofrece una configuración al cliente.
  • request: es un mensaje generado por el cliente para confirmar/rechazar ofertas.
  • ack / nak: confirmación / negación de un mensaje de tipo request

lunes, 9 de abril de 2012

Permisos de acceso y Capifony

En el ultimo post se explico como desplegar un proyecto Symfony 2 con Capifony. Dependiendo del servidor con el que estemos trabajando debemos tener mas o menos cuidado con los permisos de usuario. Git en concreto solo guarda información sobre el bit ejecutable de un archivo. En mi caso al desplegar me encuentro con que el servidor se queja de los siguiente:
  • Carpetas 775 en lugar de 755
  • Archivos 664 en lugar de 644
Al intentar servir una pagina web en la que el archivo o la carpeta no tenga los permisos adecuados , se genera un error 500. Así que hay que hacer algo para realizar los cambios pertinentes. Seria bastante estúpido, montar todo Capifony para desplegar cómodamente con la ejecución de un comando para tener que cambiar los permisos de los ficheros manualmente.

Por defecto Capifony le dará permisos de escritura al grupo, asi que para ello hay que agregar a Deploy.rb la opción:
 set :group_writable, false  

Con eso están solucionados los permisos de las carpetas, sin embargo para los ficheros no hay una opción que podamos modificar. Mirando el código de Symfony2.rb, cuando se despliega el código la ultima tarea ejecutada antes del commit es deploy:symlink asi que teniendo esto en cuenta podemos modificar deploy.rb para que cambie los permisos de los ficheros cuando termine de desplegar. Yo solo necesito eliminar los permisos de escritura para todos los que no sean el propietario.
 after "deploy:symlink" do  
  run "cd #{latest_release} && chmod -R go-w web/"  
 end  


sábado, 7 de abril de 2012

Desplegar Symfony2 con Capifony

Seguro que a más de uno con tan solo escuchar la palabra desplegar se le pondrán los pelos de punta. Si hay algo importante en las metodologías ágiles es el famoso DRY (don't repeat yourself), ¿porque romper con ese enfoque para desplegar? no tiene ningún sentido desplegar a la vieja usanza, lidiando con ver que ficheros subir a producción, cuales no y empezar a subir los ficheros mediante FTP o rsync. Para evitarnos esos dolores de cabeza es donde Capifony entra en juego. Capifony nos permitirá desplegar nuestro proyecto con tan solo un comando, tan sencillo como cap deploy. Aunque a ese estado no se llega por arte de magia, primero habrá que realizar ciertas instalaciones y configuraciones, así que vamos a ello.


Salvo que se indique lo contrario las instrucciones deben ser ejecutadas DESDE donde se desplegara la aplicación.

Instalación de Capifony
Para instalar Capifony debemos tener instalado RubyGems y usaremos capistrano_rsync_with_remote_cache para poder desplegar con mayor rapidez, ya que solo se subir los cambios realizados y no todo el respositorio.
 sudo apt-get install rubygems  
 sudo gem capifony  
 sudo gem capistrano_rsync_with_remote_cache  


Configuración del entorno
Lo más cómodo (y seguro) es usar ssh con nuestra clave publica, en lugar de introducir el password cada vez que vayamos a desplegar. En caso de no tener una clave RSA generada, crearla es tan fácil como seguir los pasos del asistente que se nos muestra al ejecutar:
 ssh-keygen  

Copiar la clave publica al SERVIDOR.
Personalmente tuve algunos problemas al conectarme y tratar de copiar mi calve publica desde el terminal, así que tuve que copiarlo mediante cPanel. Hay que copiar el fichero ~/.ssh/id_rsa.pub (nuestra maquina) a ~/.ssh/authorized_keys (servidor)


Para probar si la clave quedo bien instalada, hay que ejecutar:
 ssh usuario@ip -p puerto  


Si en nuestro servidor conviven PHP 5.2 y 5.3, y en el PATH solo se encuentra la versión 5.2, debemos agregar 5.3 al PATH, sino tendremos problemas (ver la ultima sección del post). Para hacerlo tenemos que modificar el fichero (en el servidor) ~/.bashrc y añadir la siguiente linea:
 PATH=/path/to/php5.3:$PATH   

Cerramos la sesión y listo.

Configuración del proyecto
El proyecto se puede desplegar de dos maneras: obteniendo el código desde desarrollo o desde un repositorio. Se detallara como hacerlo desde un repositorio externo, para ver como hacerlo desde desarrollo consultar la documentación de Capifony.

Para crear los ficheros necesarios de capifony basta con ejecutar.
 cd /path/to/project  
 capifony .  

Esto nos creara dos archivos:

  • Capfile: se encuentra en la raiz del proyecto, es el ejecutable que indica que estamos trabajando con Symfony.
  • Deploy.rb: este fichero se encuentra en app/config/ y se usara para configurar Capifony.
Ahora hay que editar Deploy.rb para configurar Capifony, vayamos por partes.

En esta sección se define lo que es la aplicación en si básicamente el nombre y donde se despliega.
 #Application 

 set :application, "acme" 
 set :domain,   "#{application}.com" 
 set :deploy_to,  "/path/to/project" 
 set :app_path,  "app" 
 set :keep_releases, 3 

 role :web,    domain 
 role :app,    domain 
 role :db,     domain, :primary => true 

 set :model_manager, "doctrine"  

La mayoría de los parámetros dejan bien claro que es lo que hacen, aunque algunas aclaraciones no estarían de mas:

keep_releases
es la cantidad de versiones (las mas nuevas) que se dejaran en el servidor al ejecutar cap deploy:cleanup, es decir si desplegamos 10 veces, tendremos 10 versiones en la carpeta releases, al realizar el clean up se eliminar las versiones mas viejas dejando únicamente las mas nuevas, en este caso tres. 

role
si estamos desplegando solo a una maquina, hay que dejarlo tal cual esta, pero si necesitamos desplegar en varias al mismo tiempo, deberá ser algo así:
 role :web, "subdom1.domino.com", "subdom2.dominio.com", "subdom3.dominio.com" 
 role :app, "subdom1.dominio.com", "subdom2.dominio.com", "subdom3.dominio.com" 
 role :db, "db.dominio.com"  

La configuración al repositorio es muy simple,  ssh_options[:forward_agent] = true le indica a capifony que estamos usando ssh para acceder al repositorio, y que la clave se encuentra en nuestra maquina, sino habría que indicar el usuario y el password.
 #Repository  
 set :repository, "url"  
 set :scm,     :git  
 set :deploy_via, :rsync_with_remote_cache  
 set :git_enable_submodules, 1  
 ssh_options[:forward_agent] = true  

Los ficheros compartidos (shared), como lo indica su nombre son compartidos, compartidos entre versiones, por lo que se mantienen de versión a versión. En las ultimas dos opciones se indica que cada vez que se despliegue se actualicen los vendors y se instalen los assets (imágenes, css, etc que se encuentran dentro de un Bundle).
 #Symfony2  
 set :shared_files,   ["app/config/parameters.ini"]  
 set :shared_children,   [app_path + "/logs", web_path + "/uploads", "vendor"]  
 set :update_vendors, true  
 set :dump_assetic_assets, true  

Finalmente se configura el acceso al servidor, si trabajamos en un servidor compartido es IMPORTANTISIMO, indicarle a Capifony que no puede usar sudo, ya que generara problemas de acceso, porque no tendremos privilegios de administrador.
 #Server connection  
 set :user, "user"  
 ssh_options[:port] = "port"  
 set :use_sudo, false  

Despliegue
Finalmente tenemos todo listo para hacer el despliegue.

La primera vez hay que crear la estructura para Capifony. Así que desde la carpeta de nuestro proyecto ejecutamos
 cap deploy:setup  

El cual creara una estructura como la siguiente:
 `-- /path/to/project  
  |-- current   
  |-- releases  
  `-- shared  
   |-- log  
   |-- config  
   `-- web  

Cada vez que despleguemos se creara una carpeta en releases con el timestamp actual, y se enlazara current con la ultima versión.

Un fichero fundamental es app/config/parameters.ini, antes de ejecutar el primer despliegue, tendremos que copiarlo a shared/app/config/parameters.ini


 scp -P puerto app/config/parameters.ini user@domain:/path/to/project/acme/shared/app/config/parameters.ini  

¡Ahora si estamos listos para desplegar!
 cap deploy  

Si, todo fue bien (esperemos que si) nuestra aplicación ya esta desplegada en producción. Y por si fuera poco Capifony nos permite acceder a la consola de Symfony directamente desde nuestra maquina, para ver todos los comando disponibles ejecutar cap -T

Posibles problemas
Sin acceso root
Leé nuevamente la sección Configuración  del proyecto ;)

No such file or directory
Este error me surgio en dos ocasiones, una haciendo referencia a una carpeta de un Bundle y otra a web/images/ y web/js/.

En el primer caso esto pasa cuando en el fichero deps en la URL de algún bundle tenemos  git=git://... en lugar de  git=http://... 

En el otro caso, capifony busca las carpetas web/images/ y web/js/ por lo que al no encontrarlas lanza el error, para solucionarlo hay que crear la carpeta en cuestión en nuestro proyecto con un fichero vacio (para que la detecte git) y agregarla al repositorio.

Parse error: syntax error
En concreto este error me dio bastante problemas, después de muchas horas pude dar con la fuente del problema. El error se genera al indicar manualmente (porque el default es 5.2) el path para el ejecutable de PHP 5.3 para reinstalar los vendors, cuando se terminan de actualizar se actualiza el bootstrap, y en ese momento es cuando se genera el error. Ya que la construcción del bootstrap se hace con el ejecutable de PHP que se encuentra en el path.

Para solucionarlo hay que agregar al PATH la ruta donde se encuentra PHP 5.3. En caso de no poder modificar el path por algún motivo en concreto habría que modificar el shebang de los ficheros que están dando problemas, indicando manualmente la ruta de PHP 5.3, esto ultimo no es muy aconsejable, pero bueno nos puede sacar de un apuro.