domingo, 6 de diciembre de 2009

Python Cliente-Servidor

Va la programación de un cliente y un servidor en python. Son básicos, pero salieron en cuestión de 40 minutos y sirve para ver como funciona!
Aqui va entonces el cliente:


'''
Created on Oct 1, 2009

@author: Bernardo
'''
import socket

s = socket.socket()
s.connect(("localhost",9999))
while True:
mensaje = raw_input("> ")
print "Cliente mandando mensaje..."
s.send(mensaje)
if (mensaje == "Quit"):
break
print "Adios! (Cliente)"
s.close()


... y aquí va el servidor:

'''
Created on Oct 1, 2009

@author: Bernardo
'''
import socket

s = socket.socket()
s.bind(("localhost",9999))
s.listen(10) # Acepta hasta 10 conexiones entrantes.
sc, address = s.accept()
print address
while True:
recibido = sc.recv(1024)
if (recibido=="Quit"):
break
print "Mensaje recibido: ", recibido
print "Enviando respuesta..."
sc.send(recibido)

print "Adios! (Servidor)"

sc.close()
s.close()


Saludos!

Cargar propiedades desde un archivo en Java

Suele ser útil (e imprescindible) el hecho de cargar información desde archivos de configuración. Aquí va código Java que lo realiza.



public class ResourcesManager {

private Properties properties;

public ResourcesManager(){
this.properties = new Properties();
this.loadResources();
}

private void loadResources(){
try {
this.properties.load(ResourcesManager.class.getResourceAsStream("/Archivo.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}

public String getResource(String resourceName){
return this.properties.getProperty(resourceName);
}

}


Espero que sea util. Saludos,

sábado, 28 de noviembre de 2009

Arquitectura de base de datos

Existen dos grandes tipos de arquitecturas en lo que refiere a un sistema de gestión de base de datos. Por un lado tenemos las arquitecturas centralizadas y por el otro las arquitecturas cliente-servidor. Este es un compendio con las características de cada una de ellas.

Arquitecturas centralizadas

El avance de las arquitecturas de sistemas de computadoras supuso también una revisión de otro tipo de arquitecturas, entre ellos la de los sistemas de gestión de base de datos (de ahora en más y por razones obvias SGBD o DBMS).

Las primeras arquitecturas eran llamadas Arquitecturas centralizadas y contaban con un macrocomputador o mainframe que proporcionaban el procesamiento principal a todas las funciones del sistema. Esto incluía programas de aplicación, interfaces de usuario, sumado a toda la funcionalidad de un SGBD.

Los usuarios accedían al sistema mediante terminales, que solamente mostraban en pantalla información. Se llamaban terminales tontas, dado que su única función era la de visualización. Todo el procesamiento se hacía de manera remota en el mainframe, que cuando concluía de procesar y se proponía desplegarle algo al usuario, debía comunicarse con ese terminal enviándole la información y los controles de pantalla. Dicha comunicación entre el computador central y los terminales “tontos” se hacía mediante algún tipo de red de computadores.

Los precios de Hardware habían descendido notoriamente, surgen las PC’s y la mayoría de los usuarios cambia los terminales que tenían por los nuevos PC’s dado que eran relativamente baratos, y generalmente se rompían poco. En un primer momento, la arquitectura de los sistemas no varió, se seguía usando un SGBD centralizado con PC’s remotas que se conectaban a una determinada máquina que era la encargada de realizar todas las funciones del SGBD.

Poco a poco los SGBD fueron evolucionando y la arquitectura centralizada comenzaba a ser una limitante en cuanto al procesamiento que el usuario exigía, lo cual llevó a las arquitecturas SGBD Cliente-Servidor.

Arquitecturas cliente-servidor

Las arquitecturas cliente-servidor se diseñan para manejar los nuevos entornos de cómputo, en los que hay muchos PC’s y estaciones de trabajo, servidores de ficheros, etc interconectados por medio de una red. Existen factores ajenos al desarrollo propio de la arquitectura, que son inherentes a la evolución de la tecnología en sí misma y que potencian el crecimiento de las arquitecturas cliente-servidor, como por ejemplo el bajo costo del hardware y las nuevas PC’s, o el desarrollo importante que tuvieron las redes de computadoras en ese último tiempo. Dado que las tareas se dividen en una arquitectura cliente-servidor, los requerimientos de los servidores bajan notoriamente respecto a lo que eran los mainframes.

La idea principal es definir servidores especializados con funciones específicas. Es decir, conectar un cierto número de estaciones de trabajo o PC’s como clientes de un servidor de ficheros que se encarga de mantener los ficheros de la máquina cliente. Por ejemplo supongamos un servidor de impresoras, que posee un conjunto n de impresoras que debe gestionar. Pone a disposición de los clientes la impresora y cuando llega una petición de impresión el servidor es quién la recibe y la despacha a la impresora que considere más adecuada. Esto es extensible a todo tipo de servidores especializados dado que los recursos del servidor están a disposición de los clientes.

Por otra parte el cliente, le proporciona al usuario las interfaces adecuadas para poder usar los servidores, así como también la potencia para el procesamiento para las aplicaciones locales.

La misma idea puede también aplicarse al software, donde puede almacenarse un determinado software en una máquina y ponerlo a disposición de los clientes.

La arquitectura cliente-servidor tiene una estructura con varios PC’s y menos mainframes, todos interconectados entre sí mediante algún tipo de red de computadoras. El cliente, provee capacidades de interfaz de usuario y procesamiento local. Si alguno de los clientes solicita cierta funcionalidad adicional, entonces la máquina cliente le conecta con un servidor que proporcione dicha funcionalidad. Un servidor es una máquina que puede proporcionar servicios ya sea de impresión, de ficheros, de acceso a una base de datos, etc.

Arquitectura cliente-servidor en un SGBD

En un comienzo las bases de datos relacionales eran arquitecturas centralizadas. Con el paso del tiempo poco a poco esa arquitectura fue transformándose en una cliente-servidor. Los primeros aspectos que pasaron del lado del cliente fueron los programas de aplicación y la interfaz de usuario. De esta manera, y debido a que SQL estableció un lenguaje estándar que dividía lógicamente el cliente del servidor, las funcionalidades de transacción y consulta permanecen del lado del servidor, a menudo llamado servidor SQL o de consulta.

En una arquitectura de este tipo, los programas de aplicación y la interfaz de usuario pueden ejecutarse en el cliente. Cuando un usuario solicita acceso al SGBD, se establece una conexión con el servidor mediante el protocolo ODBC (Open Data Base Connectivity) el cuál proporciona interfaces API para que las aplicaciones del lado del cliente puedan llamar al SGBD y comunicarse correctamente. La mayoría de los proveedores de SGBD proporcionan drivers ODBC. Java tiene otro estándar llamado JDBC, que cumple una función similar.

En los sistemas de base de datos orientados a objetos se dividen los módulos del SGBD entre cliente y servidor. De esta manera el servidor se encarga de los módulos de manejo de almacenamiento de los datos en páginas de disco, recuperación, control de concurrencia, movimiento de páginas a disco y funcionalidades similares. Por otra parte, el cliente cuenta con funciones que corresponden a los módulos de gestión de interfaz de usuario, funciones de diccionario de datos, interacción entre el compilador de un determinado lenguaje y el SGBD.

Nota final:

Si se quiere puede investigarse más sobre lo referente a las arquitecturas cliente – servidor existen más tipos que requieren conceptos adicionales como por ejemplo las arquitecturas C-S de tres niveles, o incluso las base de datos distribuídas.

*Fundamentos de sistemas de base de datos, 3a edición, R. Elmasri – S. Navathe

*Sistemas de base de datos, 5a edición, Volúmen 1, C.J.Date

Catálogo de un sistema de base de datos

Acá va un material teórico que escribí hace un tiempo en el viejo blog.
Es un breve resumen que puede servir para la facultad en materias como Base de datos.
Espero les sirva!

El catálogo de un sistema de base de datos no es más que una base de datos en sí misma a veces llamada metabase. Los contenidos de dicha base de datos son llamados metadatos. La función principal del catálogo es almacenar los esquemas de las bases de datos que el sistema mantiene. Mantiene una descripción de todos los niveles (véase arquitectura de tres esquemas o niveles) tanto del esquema interno como del externo y el conceptual.

Esencialmente se guardan objetos que puedan resultar de interés para el sistema, como por ejemplo tablas, vistas, índices, usuarios, planes de aplicación, privilegios de acceso, etc. La información contenida en el catálogo es indispensable para que el sistema se comporte de manera adecuada. El conocer los índices que existen por ejemplo, facilitaría o influiría sin dudas en la planificación de la estrategia en una determinada consulta. El subsistema de autorización, chequeará por ejemplo que cada operación que intente realizar el usuario esté permitida. De manera que también vemos que el catálogo sirve para chequear la validez de una sentencia y mantener la integridad y la coherencia de los datos.

Las consultas al catálogo pueden realizarse con las mismas sentencias que se consulta cualquier base de datos o tabla. Sin embargo las actualizaciones al catálogo (INSERT, DELETE, UPDATE) no son posibles. Pensemos un segundo que pasaría si permitiéramos aplicar estas sentencias en el catálogo. Podríamos por ejemplo, borrar una línea de la tabla syscolumns (tabla que contiene una fila por cada columna en alguna tabla del sistema). Si esto sucediera estaríamos eliminando una columna del catálogo y para el sistema esa columna no existiría más. De manera que cualquier intento por recuperar datos de esa columna fracasaría.

En contraposición a estas sentencias existen otras proposiciones de definición de datos, como son CREATE TABLE, CREATE INDEX, DROP y ALTER. Cuando hacemos un CREATE TABLE, solamente se hace un ingreso en la tabla systables(tabla que contiene todas las tablas del sistema) del catálogo, sino que también se dan ingresos en la tabla syscolumns a todas las columnas que contiene la nueva tabla a crear.

De manera similar el DROP equivale al DELETE y el ALTER al UPDATE.

*Fundamentos de sistemas de base de datos, 3a edición, R. Elmasri – S. Navathe

*Sistemas de base de datos, 5a edición, Volúmen 1, C.J.Date

Fail2Ban

Como trabajo de la materia Linux, elegimos el estudio y configuración de algún software de la vuelta. Además si éste no tenía artículo en Wikipedia español debíamos hacerlo. Así fue como dimos con fail2ban, un framework escrito en Python, que básicamente se encarga de escanear logs. El usuario puede especificarle expresiones regulares, y cuando el programa encuentra dichas expresiones regulares en los logs, toma una determinada acción. La acción puede tratarse de "bloquear" una IP, un puerto, un protocolo, etc. Puede ser extremadamente útil para evitar ataques de fuerza bruta por ejemplo. En el proyecto puntualmente levantamos un servidor web (lighttpd) y cuando un usuario se logueaba mal mas de 2 veces, bloqueaba la IP desde la cuál se estaba tratando de loguear por 60 segundos.
Es todo ajustable, de manera que si queremos bloquear una IP por más tiempo, basta con cambiar 60 por la cantidad de segundos que querramos y listo!

INSTALACIÓN
Simplemente sudo apt-get install fail2ban
(Conviene tener instalado Python 2.5 previamente, sino sudo apt-get install python2.5)

CONFIGURACIÓN

Para la configuración se tienen básicamente 2 archivos importantes.
/etc/fail2ban/jail.conf
/etc/fail2ban/filter.d/archivoConReglas.conf

El primer archivo es el que contiene todas las configuraciones referentes al bloqueo que se desea realizar. Se indica que puertos se han de bloquear, el archivo conteniendo las expresiones regulares que se desean buscar, el nombre del log que se desean encajar las expresiones regulares, el tiempo de bloqueo, etc.




port = puertos que bloqueara o aplicará la penalización
protocol = protocolos que bloqueara o aplicará la penalización
filter = indica el nombre del archivo que contendrá las expresiones regulares
logpath = path al archivo de log que se quiere escanear
maxretries = máxima cantidad de reintentos de fallo
También existen otros parámetros como bantime que especifica la cantidad de tiempo en segundos que se deseará bloquear la pc atacante.

El segundo es un archivo que se crea con las expresiones regulares a buscar. En nuestro caso buscaríamos expresiones que fueran del tipo:
(http_auth.c.872).*: (Donde es un alias que contiene IP, protocolo, puerto, etc). El http_auth.c.872 es el código de error para simbolizar que hubo un intento fallido de logueo.

Es un software sumamente interesante, que acepta trabajar con la mayoría de los servidores o programas importantes (Apache,QMail, Lighttpd, SSH, entre otros).
Invito a probarlo, puede llegar a ser de gran utilidad.
Saludos!

Restaurando Grub segunda vuelta

Cambia, todo cambia... Hace unos meses tuve este problema y lo solucioné como está escrito en el post Restaurando Grub. Sin embargo ahora me sucedió de nuevo, y ya no está el Ubuntu 9.04 ni el Windows 7 Release Candidate. Ahora los actores son Ubuntu 9.10 (que trae el nuevo gestor Grub 2) y el Windows 7 definitivo.
Grub 2 es bastante diferente que Grub en varios aspectos, archivos de configuración diferentes, nombre de variables también diferentes, etc.
Para restarurar grub 2 y que vuelvan a aparecer Windows 7 con Ubuntu 9.10 Karmic Koala, hay que seguir los siguientes pasos:

1. Bootear con un live cd de Ubuntu que se tenga a mano

2. Escribir en consola "sudo fdisk -l" (para listar la tabla de particiones y saber en qué partición tenemos instalado Ubuntu 9.10)

3. sudo mount /dev/sda1 /mnt (dnd sda1 es la partición en la cuál tenemos Ubuntu 9.10, en mi caso sda1)

4. sudo mount --bind /dev /mnt/dev (con este comando montamos el resto de los dispositivos)

5. sudo chroot /mnt (ejecutamos chroot para poder acceder como root a nuestro sistema de archivos)

6. grub-install --recheck /dev/sda (con este comando cargamos Grub en el MBR del sda, disco indicado. OJO! DEBE SER EL DISCO Y NO EL NÚMERO DE PARTICIÓN, SI PONES EL NÚMERO DE PARTICIÓN PROBABLEMENTE PIERDAS WINDOWS).

7. Reiniciar y cuando arranca el Ubuntu 9.10 de nuestra pc hacemos:
sudo update-grub2

Espero les sea de utilidad. Son pocos pasos y rápidos y pronto tenemos nuestro Ubuntu/Windows andando de nuevo.
Saludos!

jueves, 12 de noviembre de 2009

Cambiando usuario en un script

Los otros días se nos presentó un problema que parecía trivial pero que demandó un poco mas de tiempo que el esperado. El mismo consistía en levantar una serie de aplicaciones al inicio sin inconvenientes de que las mismas fueran levantadas como root, a excepción de una. De manera que lo que se nos ocurrió fue desde el arranque hacer un script que levantara todas las aplicaciones con root y al final cambiarse de usuario con el famoso su y ejecutar los comandos con el nuevo usuario. Sin embargo, esto no funcionó. :-( Por el contrario, y luego de un ratito explorando el man y algunos foros, encontramos lo siguiente:

#!/bin/bash

su - usuario1 -c "touch /home/usuario1/ejemplo.ok"

exit 0

Ejecuta un comando con el usuario especificado. Sin misterios :-D.
Gracias a Agustin con el que remamos esto!!!

sábado, 31 de octubre de 2009

Restaurando grub

Tenía en mi pc dos particiones en las cuales en cada una tenía instalado Windows Vista y Ubuntu 9.04. Dado que el vista no caminaba del todo bien, y ante la salida del Windows 7, decidí instalarlo y probarlo (y la verdad que está sustancialmente mejor que su antecesor). Sin embargo al instalarlo pasó por arriba al MBR y se hacía imposible el booteo de Ubuntu. Navegando un pocó encontré la solución al problema.
1. Bootear con un live cd y montar la partición en la cual se encuentra Ubuntu.
Escribir en consola:
2. sudo grub
3. root (HDX,Y) #Donde X es el número de disco e Y la partición.
4. setup HDX
5. quit

(HDX,Y) hacen referencia al disco y partición, por ejemplo (HD0,1) es la segunda partición del primer disco (recuerden que las numeraciones comienzan en 0).
Como nota si no saben en qué disco/partición se encuentra instalado Ubuntu pueden escribir en la consola del grub (luego de “sudo grub”) “find /boot/grub/stage1″.

Espero que le sea te utilidad! Saludos!!

Hola mundo!!!

El primer post inaugurando el blog!
Bienvienidos!
Trataré de escribir sobre mis experiencias, vivencias, tecnologías, etc.
Al principio copiaré un par de post de un viejo blog que tenía y que siguen vigentes hoy en día!
Espero que les parezca tan divertido como a mi!
Como buen informático el primero mensaje no puede ser diferente a un Hola mundo! Así comienza todo en nuestra vida cuando queremos aprender algo nuevo. Así empiezo este blog.
Dejo un link de un concurso que se hizo hace unos años.

http://wiki.cld.org.uy/index.php?title=Concurso_Hola_Mundo

Nos leemos.

sábado, 15 de agosto de 2009

Creo...

Creo....
En las decisiones que se toman en dos segundos y cambian un problema por una alegría;
en las buenas personas;
en las personas magicas;
que el trabajo en equipo es lo mejor de cada uno y que ninguno puede lograrlo solo;
en el determinismo;
en el hacer racional;
que el capitalismo es natural e instintivo;
en los buenos hábitos;
en la planificación;
en la pc como uno de los mayores inventos de la humanidad;
que tener convicciones es bueno y...
que no tenerlas es turbio y peligroso;
que la felicidad es importante (lo más importante);
y que en el mundo que vivimos, el dinero también.

Creo...
que la buena música calla a muchas personas.
Que en momentos de crisis, solamente la creatividad y los “otros puntos de vista” son las mejores (tal vez únicas?) soluciones;
en bromear y disfrutar sin estar haciendo nada malo;
en tener tiempo para todo;
que la soberbia y la maldad puede ser callada con seguridad y amor;
que el que piensa que sin sufrimiento no se puede lograr nada, es una persona que vive equivocada siempre;
en que todos tenemos un cajoncito donde va todo el desorden y está bien, mientras el cajoncito no sea la vida entera;
que no hacer nada también es una manera de disfrutar;
que el cuestionamiento es bueno, hasta determinado punto;
que el equilibrio es posible y necesario;
que una persona que necesita tiempo, lo pierde;
que el sexo es bueno y extremadamente necesario;
que entre todo y un poquito elijo el todo, y no peco de soberbio.

domingo, 18 de enero de 2009

La universidad privada

Con 18 años y recién salido del liceo me encontré, como tantas otras personas, en la encrucijada de decidir entre la Universidad privada y la Universidad pública. Lamentablemente decidí algo que dos años después debí corregir. Escuché, me informé, busqué y un par de detalles más me hicieron poner la camiseta de la pública. Ya el día que me fui a anotar me citaron a las 8.00 y me atendieron a las 18.00, pero bueno... era el primer día, cuántas ilusiones, cuántos sueños... digamos que se bancaba. Las cosas que viví en esos dos años, no caben en todo un blog sobre eso. Los desprecios mas grandes, los "plantones" más descabellados, las sobradas mas insoportables. Allí conocí la soberbia, el rencor, la maldad. Todo lo que antes conocía bajo esos significados eran simples juegos de niños. Llegué a pensar que el mundo era una porquería, que nada valía la pena, que tanta mala intensión no podía ser contrarrestada con nada. Que el amor era mas fuerte, pero no iba con la facultad. Que todo era incompatible. Y ya ahí, en segundo y con una úlcera me puse fuerte. En el momento mas vulnerable de mi vida fui mas fuerte. Decidí el cambio. Sabía que académicamente no era lo que me vendían. Ni locos. Que "educaban personas en los dos primeros años", como dicen, bueno, no creo en absoluto eso, pero en cualquier caso esos dos años ya los había pasado y si algo tenían para eduarme, lo habían hecho. Así fue como tiré todo y comencé de nuevo. Con el apoyo en casa, de todos, logré cambiar de paradigma (sí! de paradigma). No me importaba empezar todo de nuevo, tirar por la borda todo aquello que había logrado. Solamente olvidar pronto, sacar lo bueno, y seguir. Y así fue como en el 2006 entré a la Universidad privada. ¿Es mas fácil? No. ¿Es más caro? Depende, si sumo los medicamentos de la úlcera que me costó la pública y su maldad, seguro que es mas barata. ¿Pagás y pasás? Ni loco. Le discuto al que sea eso. El que habla eso habla desde el resentimiento, y desde la total ignorancia. Lo vivo a diario como alumno en el que paso días enteros estudiando y lo vivo desde el otro lado del mostrador, en donde nunca jamás se ayudó a alguien porque "pagara", o al menos desde que doy clases. Sin dudas creo que son dos tipos de universidades que apuestan a cosas diferentes. Desde mi experiencia en conocer ambas facultades de ingeniería puedo decir que creo en la formación que brinda la Universidad Católica. Confío en que en un futuro las materias como Ética, Antropología filosófica, Gestión, Epistemología, Argumentación, entre otras que se enseñan (como materias curriculares y obligatorias), marcan o marcarán una diferencia. Que es mejor tenerlas que no tenerlas no tengo duda. Que como ser humano me ayudaron a pensar y meditar tampoco tengo dudas. Que las aplico a diario: seguro que si. La diferencia con otras universidades radica en la inexistencia de estas materias, a costa de mayor carga en matemática, por ejemplo. Y está bien, la manera de pensar la matemática, de enfrentarnos a los problemas es lo que rescatamos. Pero la importancia de lo humano es trascendente. Sobre todo en un mundo en que los ingenieros son quienes construyen las bombas, los instrumentos de matanzas y torturas mas grandes. Hace falta una gran cuota de humanidad en una carrera fría. Ese fue mi pensamiento durante esos dos años de estadía en la universidad del estado. Y casi sin esperanzas encontré ese baño de humanización en la UCU. .

Solamente me gustaría alejar un poco ese pensamiento que tenemos en este país de que todo lo privado es malo y todo lo público es bueno o viceversa. Existen diferentes puntos de vista de la misma cosa, todos tan válidos como se quiera creer. Sin embargo no se trata de absolutismos ni recetas mágicas. Se trata de ser humanos y pensar desde ese lado. Lejos de la ignorancia que absolutiza y de los resentimientos. Hay cosas públicas buenas y malas. Como las hay privadas.

Desde aquí solamente un intento de contar un pedacito de mi vida. Pueden o no coincidir, puede o no gustar, simplemente es lo que viví y eso no me lo quita nadie. Fue mi manera de percibir el mundo en que me tocó (y me sigue tocando) vivir.  Y desde luego, hace ya 3 años, que lo vivo de una manera mucho mas tranquila y feliz.

jueves, 15 de enero de 2009

Apuntes de Python

Algunos apuntes de Python que pueden ser útiles. Me los pasó Ignacio Corderi que tomó esas notas en la primera de las reuniones. Aquí van, espero que les sea útiles.

Apuntes Python

Dos primeras instancias de SAGE

Se llevaron a cabo las dos primeras instancias del grupo de SAGE-Python. Debo confesar que cuando pensamos en el grupo un máximo de 6 o 7 personas nos dejaba mas que conformes. Finalmente luego del posteo en el foro de la apertura del curso, mi casilla se llenó con 20 mails de personas interesadas. Cuando repasaba nombre a nombre, notaba que el interés era real. Que se trataba de los alumnos más aplicados y más comprometidos de la clase. Un par de reuniones con Leonardo (un fenómeno, de verdad!) bastaron para entendernos y saber que esperábamos del grupo. Deberíamos nivelar de alguna manera los conocimientos de algunos para poder lograr una base y construir encima. Se trata de alumnos de primer año, y quizás lo buscado tanto a nivel de programación como matemático excedía un poco sus conocimientos. Deberíamos cumplir con la comprensión del lenguaje en primera instancia, desconocido por la mayoría de ellos. Un nivel mas arriba, estaba el trabajar con algún servidor SVN (que finalmente echamos mano al google code, dado que en la universidad se nos complicaba instalar uno). La manera de trabajar con el programa era en general conocida por todos ya que habíamos apostado a eso en el curso de Cálculo II. Debo agradecer desde siempre a Leonardo por su gran apoyo y referente, a Santiago que cuando Leonardo estuvo enfermo se puso el equipo al hombro, preparó en un día los temas y llegó ese sábado temprano a contagiar a todos como nos tiene acostumbrado. Los chiquilines impactados por Santiago y cada vez mas entusiasmados. El curso sirvió como gran guía de los proyectos que cada uno tenía como obligatorios. Cada uno, en mayor o menor medida agregaban funcionalidad al software de manera que puedan ser usado por diversas materias en la carrera.
Valoro por sobremanera el interés y compromiso que mostraron desde siempre los muchachos que siempre preguntaban cuando teníamos jornada, cuando podíamos juntarnos, consultar, etc. No se que seguirá de todo esto, si serán todos, pocos o algunos, sin embargo para el comienzo que esperábamos tener, desde todo punto de vista lo superó.

[gallery]

(Este post quedó guardado en borradores por error! Debió haber sido publicado el 30/10/2008 )