Mi tesis

Decidí escribir sobre mi tesis.

Primero hablaré el porque tome este camino y no pasantía. Lo primero, trabajo para mi mismo y mi compañero, es decir, yo dispongo de mi tiempo. Segundo, trabajar usualemente es algo muy mecánico y en la cual uno no toca temas interesantes  de la teoría de la computación, la cual me parece full interesante. Con éstas razones, sumándole de tener un buen compañero y una profesora dispuesta a ser tutora, se dió el proyecto.

Mi tesis trata sobre clustering de datos, el cual hoy en día es usado en diversas aplicaciones, como lo son Data Mining, preprocesamiento de imágenes, etc. Es una búsqueda no supervisada (no se tiene información previa y se clasifica desde cero). Es un problema NP-Hard.

La manera para atacarlo fue mediante metaheurísticas. Éstas son algoritmos, génericos, por ello la palabra meta, que usan suposiciones/intuiciones que no siempre dan resultados exactos, de ahí la palabra heurística. Hay montones: genético, búsqueda Tabu, algoritmo hormiga, PSO, simulated anieling, etc. Mi compañero y yo implementamos 5 de ellas, basadas todas en población e inteligencia colectiva.

La implementación fue en C++. Para este tipo de problemas se quiere un lenguaje que compile a código de máquina. Se busca eficiencia. La diferencia entre C y C++ es mínima en tiempo, siendo este último preferible por ser orientado a objetos.

De todo lo que se hizo, lo que mejor quedó fue el algoritmo genético. Dió los mejores resultados, es muy flexible, eficiente, etc. Mi compañero y yo hemos estados haciendo pruebas, cambiando y mejorando el código para ver si con la tutora, que tenemos abandonada, logramos escribir una publicación. El código ha sido reescrito y mejorado. Ahora es super entendible y a su vez bastante efieciente. Ya en uno de mis post toque el tema de mis intentos y logros por hacer el código mas efieciente.

Es bastante divertido saber la cantidad de lenguajes que usamos. Además de C++, se usan Python, Haskell y Latex, cada uno para cosas diferentes. Para el manejo de versiones se usa GIT. Ya veremos que sucede, posteo unas imágenes para demostrar lo que es capaz de hacer:

Antes:

Peppers

Después:

Peppers, Resultado

Antes:

Lenna

Después:

Lenna, Resultado

Antes:

Fotografía

Después:

Fotografía, Resultado

Finalmente una imagen de la cual se pueden conseguir patrones escondidos:

John Lennon

Eso es todo, hablamos !

Advertisements

Mi opinión sobre Caracas cuidad de despedidas

No soy muy escritor ni nada por el estílo, pero creo que debo expresar lo que siento al respecto.

Primero quiero aclarar que conozco a Ivanna, la cual me invitó a ver el estreno, y otros que participaron(Adriana, Paul, etc). Cuando vi el video no me gusto, pero respete su opinión, fue un punto de vista del asunto.

El video me parece que es totalmente parcializado hacia gente de clase alta y super sifrina. Sumado eso con la falta de seriedad del asunto fue mi motivo de disgusto hacia el video. Si vas a tocar un tema tan delicado, me parece que hay que hacerlo de un modo más serio e imparcial, mas siendo estudiante de comunicación social donde esa es una de las premisas del código del periodista.

Algo que sí estuve muy de acuerdo y  es muy cierto: muchas personas se están yendo. El año pasado cinco de mis amigos se fueron, tenía una amiga estudiando afuera y así hay muchos más que se han ido. Creo que queda muy claro y seguro muchas personas, de mi círculo social (clase media/alta) les sucede lo mismo. Y quien le quita a que no pase en estratos inferiores. Pero ese no es el punto.

La gente esperaba un documental al nivel de  Globovisión o algún canal famoso. Se encontraban con un video hecho para una materia y sus amigos, en especial. Solución: insultar, decirles apátridas, escuálidos, etc.

Por lo visto ahora todo el mundo ama a su país, y le encanta insultar a los demás. Como dicen no te vayas, quedate y arregla el país. Bueno les digo lo mismo al respecto al documental, haz otro sino te gusta … Lo más fácil en la vida siempre será destruir, insultar, etc. En cambio crear siempre será lo más difícil.

Yo me pongo a pensar desde mi punto de vista. Soy un ingeniero graduado de una universidad que se anda cayendo al suelo. El nivel académico va en picada, y el de las universidades de afuera es mucho mejor, es claro que quiero hacer un postgrado afuera, porque voy a crecer más como profesional. Con respecto al salario, es una basura lo que puedo hacer con él. Pongamos que gano Bs4000 poniendo un promedio de un recien graduado. Con eso sólo compro mi comida y vivo normal. Si quiero independizarme, estoy jodido, con eso alquilo una casa en guarenas si acaso, no me daría para comer  y además tengo que pagar mil otras cosas: luz, agua, teléfono, etc. Hay otros países lo que puedo hacer con lo que ganaría es mucho mayor, hasta un nivel de poder ser independiente. Otro asunto super importante es la inseguridad. He sido víctima de ella(me robaron mi celular/ipod/cartera). Las noches es un peligro y no paro de escuchar cuentos de secuestros. Es cierto salgo en las noches, pero es una apuesta cada vez. La burocracia para hacer las cosas, la corrupción, la políticas. Todos son razones válidas para abandonar el país. Ahora para responder al contra argumento de quedate y cambialo. Pregunto, ¿alguna vez un político independiente ha logrado algo en este país? No. Hay que entrar en un partido político, hundirse en el aparato de la corrupción y la jaladera de bola y capaz uno logra hacer algo, que no rompa con los intereses ajenos.

Yo me quiero quedar acá haciendo mis estudios afuera, pero la situación actual hacen que uno sí tiene la oportunidad y conviene, lo mejor es irse del país por muy chimbo que suene. Esa es mi opinión, que triste ver la cantidad de insultos y odio de las personas, una crítica constructiva es lo que todo el mundo debió hacer, el país esta lleno de odio y resentimiento.

Anime

Me provocó escribir sobre una de mi pasatiempos preferidos: ver anime.  Mi idea es hacer una reseña y dar cierta opinión.

Desde que veo televisión siempre me gustaron las comiquitas. Empecé viendo Tom y Jerry, Scooby Doo y muchas de esas comiquitas. Luego a medida que crecí, se hizo famoso las tarde con Televen: dragonball, samurai x. Y también otras como super campeones, etc.  El apogeo mayor se dío fue con Locomotion. Creo que vi casi todas las series que pasaban por ahí: evangelion, saber marionette j, la secuela, those who hunt elves, bubblegum crisis, etc. Claro que todo lo bueno tiene su final y el canal cerró. Seguí viendo televisión normal y de vez en cuando una que otra cosa por Cartoon Network, estilo Inuyasha, pasaron Gundam Wing. Luego llegó Animax a mi casa y vi una que otra serie. Me gradue del colegio y ahí con el auge del internet empece a buscar otras series que ver. La primera que siempre quise terminar de ver fue initial D. Luego empece a ver naruto, bleach. Mi agradó fue aumentando a medida que pasaba el tiempo y fuí conociendo nuevas series. Y así ha pasado el tiempo hasta el día de hoy, donde leo uno que otro manga y sigo como 4 series aproximadamente y veo una que otra de vez en cuando.

El anime me encanta, me parece una buena manera de relajarse y pasar el tiempo. Uno debe estar claro que es hecho por japoneses y su cultura está métida fuertemente en lo que uno ve. Siempre me ha encantado esa cultura y me agradan full cosas. Usualmente las cosas que hacen son para el niño que uno lleva por dentro, pero tienen muchas reflexiones y cosas de adultos. El anime no son comiquitas, es algo que hace a uno pensar y reflexionar.

Géneros del anime hay miles y me gustan son los de acción principalmente, en especial los mecha(de robots).  El género echi y ese tipo de cosas si no son de me agrado.

Quisiera tocar varios animes que he visto y recomendar algunos cuantos.

  • Code Geass: Mi anime favorito de todos los tiempos. Cuenta la historia de una realidad alterna donde inglaterra es duena de 75% del mundo y Japón es uno de sus dominios. El personaje principal es uno de los tantos principes de inglaterra, el cual es llevado a Japón y abandonado por su padre y su madre fue asesinada. Éste obtiene un poder llamado “geass” el cual le permite dar una orden, sea cual sea, a una persona para hacer lo que le provoque. En la historia pasan muchas cosas, y es impresionante el ingenio de este personaje. El anime no son flores con rosas tampoco. Y lo mejor es el final, para mi fue perfecto, el mejor.
  • Evangelion: Muy bien anime. Marcó mi infancia debo decir. Los dibujos son otra cosa. La historia es algo extraña y compleja. Trata de robots y unos seres malos que vienen a la tierra para destruirla. Tengo un buen tiempo sin volverla a ver. Los remakes que andan sacando están excelentes y 100% recomendables.
  • Fullmetal Alchemist: Voy a hablar de ambas series que han sacado. La primera muy buena, me agrado bastante. Trata sobre dos hermanos que hacen alquimia y han efectuado prácticas prohibidas(tratar de revivir a su madre) y sus andanzas para cumplir ese objetivo. Bastante bien hechos los personajes y la historia. La segunda, además de tener una mejor animación, fue 100% apegada al manga. La historia como tal el principio es la misma, pero cambia. A mi me parecio mejor que la primera, exceptuando el final, no fue malo, pero mucho mejor el primero.
  • Death Note: Muy muy buen anime que maneja muchos temas morales y éticos. Trata sobre un niño genio que se consigue un Death Note(diario) donde puede anotar el nombre de las personas y su forma de morir, logrando que sucedan éstas cosas. El conflicto surge cuando se vuelve en un asesino de asesinos y llega otro personaje(L) a capturarlo. La historia es muy bien llevada y lo mantiene a uno pegado.
  • Fate/Zero: Es la precuela de Fate Stay Knight, es buena. Trata de una guerra por el santo grial donde se tiene un heroe del pasado luchando. El personaje principal es el rey Arturo, que en la historia lo ponen como una mujer. Los dibujos son muy muy buenos y la historia no es mala. Vale la pena verla.
  • Steins;Gate: Pondría este entre mis tops anime. Debo decir que no me agrado al comienzo, pero lo empece a ver, los personajes se desarrollaron y la serie supo atraparme. Es muy buena, me encantó toda la historia y el final es lo que uno menos se espera. Muy pensada la serie, la recomiendo muchisimo.
  • Mobile Suit Gundam 00: He visto como 8 gundams (Wing, turn A gundam, seed, seed destiny, unicorn, empece a ver el primero) este en verdad ha el mejor o uno de los mejores. Es un posible futuro en el ano 2300 donde el petroleo no vale nada y se tienen 3 elevadores gigantes para obtener energia solar. Un científico visionario 200 anos atras establece un plan para poner el orden al mundo y crea unas teconologías y robots(gundams) para cumplir este fin.
  • Samurai X: Excelente anime con una historia increible. Las OVAS son la cúspide de la serie. Marco mi infancia y siempre puedo verla de nuevo.

Hay muchos otros animes, pero quise comentar de los que han dejado algo y quisiera compartir al resto del mundo. Quedan muchos por mencionar. Actualmente estoy viendo el ultimo de Gundam, en el cual, la historia me está agradando mucho. No es usual ver un anime así. Espero que mi opinión ayude a muchos otros. Hablamos !

Google Maps

Estos días estuve un rato largo lideando con Google Maps para aprender de él y ver sus posibilidades.

El ejemplo que hice es simular un mapa de los Estados Unidos donde se pueden ver diversas propiedades.

Antes que nada hay que obtener un API Key mediante una cuenta de google y de esta forma poder usarlo.

Otra cosa de las cosas usadas fue JQuery. Ya teniendo estás dos cosas se puede echar cógido.

Se puede usar Google Maps de dos formas: una llamada totalmente secuencial y otra asíncrona. El ejemplo usa está última:

En el Javascript:

function loadScript()
{
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "http://maps.googleapis.com/maps/api/js?key=APIKEYo&sensor=false&callback=initialize";
    document.body.appendChild(script);
}
function initialize()
{
    var myOptions = {
        zoom: 4,
        center: new google.maps.LatLng(38.68551, -99.22852),
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        minZoom: 4,
        maxZoom: 16
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
$(document).ready(function () {
    loadScript();
});

En el HTML:

<div id="map_canvas"></div>

De acá uno puede empezar a complicar más la cosa. Lo siguiente sería agregar una imagen donde se hizo click en el map, que está al hacerle click salga una ventana de información y ademas debajo del mapa salga un div con un link para eliminarla.

Dentro de la función initialize se coloca lo siguiente:

    image = new google.maps.MarkerImage('path/image.png',
    new google.maps.Size(20, 32),
    new google.maps.Point(0, 0),
    new google.maps.Point(0, 32));
google.maps.event.addListener(map, 'click', function (event) {
    addMarker(event.latLng);
});

La función addMarker es la siguiente:

function addMarker(location, name)
{
    if (name == undefined) name = "default";
    if (markers[name] == undefined) markers[name] = [];
    var marker_number = markers[name].length;
    var contentString = '<div id="marker_info"><h2>Excelente localidad</h2></div>';
    var infowindow = new google.maps.InfoWindow({
       content: contentString,
       maxWidth: 150
    });
    var marker = new google.maps.Marker({
        position: location,
        map: map,
        icon: image,
        title: location.name
     });
    google.maps.event.addListener(marker, 'mouseover', function () {
        infowindow.open(map, marker);
    });
    google.maps.event.addListenerOnce(marker, 'click', function () {
        $('#marks').append('<a href="#" marker="' + marker_number + '">Eliminar- ' + marker_number + '</a>');
        $('[marker=' + marker_number + ']').click(function () {
             removeMarker("default", marker_number);
            $(this).hide();
        });
    });
    markers[name].push(marker);
}
function removeMarker(name, number)
{
    markers[name][number].setMap(null);
    markers[name][number] = null;
    swap(markers[name], number, markers[name].length - 1);
    markers[name].length -= 1;
}
function swap(array, a, b)
{
    var aux = array[a];
    array[a] = array[b];
    array[b] = aux;
}

Markers va a ser un diccionario que mapea a arreglos de marcadores.  Debajo del div donde está el mapa de google se coloca el siguiente:

<div id="marks">Haz click para eliminar </div>

Con lo siguiente se va a poder agregar marcadores en el mapa que muestran información y poder eliminarlos.

Vamos a complicar esto un poco más. Creemos una función para agregar polígonos y otra que simula búsquedas. Para ello agregamos las siguientes funciones:

En el Javascript:

function searchAddress(address, remove)
{
    var houses = searchResults[address];
    if (houses == undefined) {
        geocoder.geocode({ 'address': address }, function (results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                map.setCenter(results[0].geometry.location);
                alert(results[0].geometry.location.latitude + ', ' + results[0].geometry.location.longitude);
            }
            else
                alert("Geocode was not successful for the following reason: " + status);
        });
    }
    else if (houses.length == 0) return;
    else
    {
        var maxX = -360.0,
        maxY = -360.0,
        minX = 360.0,
        minY = 360.0;
        var coordinates = []
        if (remove)
        {
            for (name in searchResults)
            {
                removeMarkers(name);
                removePolygon(name);
            }
        }
        for (house in houses)
        {
            if (houses[house].longitude < minX) minX = houses[house].longitude;
            if (houses[house].longitude > maxX) maxX = houses[house].longitude;
            if (houses[house].latitude < minY) minY = houses[house].latitude;
            if (houses[house].latitude > maxY) maxY = houses[house].latitude;
            addHouseMarker(address, houses[house]);
            coordinates.push(new google.maps.LatLng(houses[house].latitude, houses[house].longitude));
         }
         addHousesPolygon(address, coordinates);
         var southWest = new google.maps.LatLng(minY, minX),
         northEast = new google.maps.LatLng(maxY, maxX);
         var bounds = new google.maps.LatLngBounds(southWest, northEast);
         map.fitBounds(bounds);
         var center_location = new google.maps.LatLng((minY + maxY) / 2, (minX + maxX) / 2);
         map.setCenter(center_location);
     }
}
function searchAllAddress()
{
    var maxX = -360.0,
    maxY = -360.0,
    minX = 360.0,
    minY = 360.0;
    for (address in searchResults)
    {
        var houses = searchResults[address];
        var coordinates = []
        for (house in houses)
        {
            if (houses[house].longitude < minX) minX = houses[house].longitude;
            if (houses[house].longitude > maxX) maxX = houses[house].longitude;
            if (houses[house].latitude < minY) minY = houses[house].latitude;
            if (houses[house].latitude > maxY) maxY = houses[house].latitude;
            addHouseMarker(address, houses[house]);
            coordinates.push(new google.maps.LatLng(houses[house].latitude, houses[house].longitude));
        }
        addHousesPolygon(address, coordinates);
    }
    var southWest = new google.maps.LatLng(minY, minX),
    northEast = new google.maps.LatLng(maxY, maxX);
    var bounds = new google.maps.LatLngBounds(southWest, northEast);
    map.fitBounds(bounds);
    var center_location = new google.maps.LatLng((minY + maxY) / 2, (minX + maxX) / 2);
    map.setCenter(center_location);
}
function removeMarker(name, number)
{
    markers[name][number].setMap(null);
    markers[name][number] = null;
    swap(markers[name], number, markers[name].length - 1);
    markers[name].length -= 1;
}
function removePolygon(name)
{
    if (polygons[name] == undefined) return;
    polygons[name].setMap(null);
    polygons[name] = null;
}

A la sección cuando el documento está listo:

$('#search_address_button').click(function () {
    var address = $('#search_address_text').val();
    searchAddress(address);
});
$('#search_address_text').click(function (event) {
    var keyDown = (event.keyCode ? event.keyCode : event.which);
    if (keyDown == 13)
        searchAddress();
});
$('.state_address').click(function () {
    var address = $(this).attr('address');
    if (address == "all")
        searchAllAddress();
    else
        searchAddress(address, true);
});

Y en el HTML:

<div id="address_selector">
    <div id="state_selector">
        <a class="state_address" address="california" href="#">California</a>
        <a class="state_address" address="washington" href="#">Washington DC</a>
        <a class="state_address" address="florida" href="#">Florida</a>
        <a class="state_address" address="ny" href="#">New York</a>
        <a class="state_address" address="utah" href="#">Utah</a>
        <a class="state_address" address="la" href="#">Los Angeles</a>
        <a class="state_address" address="default" href="#">Mines</a>
        <a class="state_address" address="all" href="#">All</a>
    </div>
    <div id="search_address">
        <input type="text" name="search_address_text" id="search_address_text"/> <input id="search_address_button" type="button" value="Search"/>
    </div>
</div>

searchResults es un arreglo que van a ver en los fuentes que publique con datos que yo mismo genere para probar.

Acá se me es algo complicado explicar el código, no encuentro como poner el código mejor y lo otro que sucede es que es mucho escribir y no tengo mucho tiempo.

Les colocó los dos archivos para que lo vean con más detenimiento y lo prueben si desean:

Javascript:

http://pastebin.com/mRu5H2kG

HTML:

http://pastebin.com/B3Z4GQNB

Tratando de optimizar el código

Ya casi no tengo mucho tiempo para escribir cosas interesantes :S!

En los siguientes post me gustaria hablar de javascript y Google Maps.

Mi tesis(https://github.com/fedep3/Metaheuriscticas-Data-Clustering) está hecha en C++ y es sobre data clustering  de datos numéricos usando metaheurísticas. Esta enfocada en las imagenes principalmente (las imágenes no son mas que conjuntos de vectores de uno o mas colores).

Actualmente ando investigando y mejorando el código para hacer una poblicacion sobre el algoritmo genético que cree yo con mi companero.

En el código he hecho dos cambios:

  1. Cambiar el generador de numeros aleatorios.
  2. Intentar optimizar la función de la distancia euclideana.

El motivo de l primer cambio era que el generador de numeros aleatorios de C++, es un http://en.wikipedia.org/wiki/Linear_congruential_generator , los cuales son muy eficiente, pero no son tan buenos. Habiendo usado python y ya de hace un tiempo que habia leído del tema decidí colocar el http://en.wikipedia.org/wiki/Mersenne_twister que es de los mejores, por no decir el mejor actualmente. Ahora el reto era buscar que implementecion usar o si hacerla uno mismo. Buscando y probando consegui uno creado por un invetigador de Pixar que hace uso de las instrucciones SSE2 y que es increiblemente eficiente(http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/cpp_sse2.zip).

Al principio no me compilo asi que busqué lo que estaba pasando. Después de como 1 hora de leer y probar di con la solucion. El código hace uso de unos defines o funciones que por lo visto no estan incluidos en el emmintrin.h. Basto con cambiar el código y listo compilo.  Lo arregle para usarlo y la diferencia de tiempo/resultados con lo que tenia antes ni se notaba.

Averiguando todo este, me surgió un interés por esas instrucciones SSE2. Quería ver si podía programar en ellas la distancia euclideana. Encontre una especia de API de ellas (http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/index.htm#intref_cls/common/intref_sse2_int_load.htm) y leyendo otras cosas(http://fastcpp.blogspot.comhttps://developer.apple.com/hardwaredrivers/ve/sse.html) entendí su funcionamiento. Las intrucciones son capaces(segun leí y entendí) de procesar 4 flotantes a la vez o 2 doubles.

Mi tesis usa floats, asi que programé lo siguiente:

float Metaheuristic::euclideanDistance(float* v1, float* v2)
{
    __m128 sum = _mm_setzero_ps(), square;
    for(register int k = 0; k < M; k+=4){
        square = _mm_sub_ps( _mm_load_ps(v1 + k), _mm_load_ps(v2 +k));
        sum = _mm_add_ps(_mm_mul_ps(square,square), sum);
    }
    sum = _mm_sqrt_ps(sum);
    _mm_store_ps(eDistance, sum);
    return eDistance[0];
}

Surgieron un montón de problemas para lograr que éesto funcionara. El principal fue que los arreglos que usan estas instrucciones deben tener tamaño divisible entre 4, ya que se cargan los 4 flotantes a los registros. Cambie gran parte del codigo para que a la hora de crear los objetos se cumpliera esta condición y probé de no tener leaks o errors en la memoria usando valgrind. Cuando ya no tuve problemas y los resultados de las corridas tenían coherencia, observé los tiempo. Una imagen que me corria antes en 1 – 2 segundos pasó a 10 segundos !

Mi intento por optimizar el codigo fue fallido, pero aprendi algo. Para mi la razón de que no funcionara muy bien es que los arreglo en realidad eran arreglos de tamano 1 o 3 transformados a 4. Más tiempo se perdía en la carga y cálculo que el que ganaba de tener la capacidad de procesar 4 cosas a la vez. Eso que hasta intente tener las cosas aleanadas a 16 bytes y nada ! Por supuesto que es posible que halla hecho algo mal, pero ahora no tengo mucho tiempo para seguir jugando con el código, ando full de otras cosas.

Espero que ésto sea de ayuda

XSRF Django

En la web uno se debe cuidar de tres cosas (y muchas otras, pero de las principales y más comunes para mí) son: inyecciones SQL, XSS y XSRF.

La primera como dice el nombre es simplemente a través de llamadas HTTP ingresar código de SQL (esto puede aplicar a otro tipo de bases de datos No-SQL). La forma más común es a la hora de un formulario por el cual se pasan datos bien sea por POST o GET, colocar valores estílo ‘; comando sql;  por medio del cual se pueden robar valores, dañar la base datos, etc.

Luego tenemos los XSS, siglas de cross-site scripting, lo cual es ingresar código en la página que se ataca. Ejemplo un párametro que se pasa por GET y que se imprime en la página. Con poner en ese parámetro algo estilo < iframe src = “http://paginamaliciosa” > </ iframe >  se logra que otras personas vean lo que uno desee y se puede robar información u otras cosas.

Finalmente tenemos el XSRF, siglas de cross-site request forergy. Éste ataque es más complejo, pero puede hacer mucho daño. Consiste en hacer que un usuario autentificado en una página haga cosas que él no autorizo. Un ejemplo sería el siguiente:

  • Un usuario anda autentificado en X página, la cual hace el cambio de contraseña por POST.
  • Una persona maliciosa simplemente debe recrear ese request de POST y hacer que el usuario lo haga sin darse cuenta.

Yo ya en un post pasado publique un link (http://google-gruyere.appspot.com/) que encontré muy bueno que habla de seguridad de páginas web y que explican de estos ataques y como defenderse.

Hable de todo ésto ya que me topé con lo siguiente:

https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

Cada día me sorprendo más con lo excelente que es este framework, al igual que Python.

De un modo bastante simple previsto por Django se es posible defenderse de éste último tipo de ataque que comente. No soy un experto de en programación web, nunca me ha gustado, pero me pregunto si muchos de los otros frameworks tienen está capacidad.

Fuera del tema, ya empezó el curso de seguridad ofrecido por la universidad de Standford, espero poder dedicarle, ya vi por encima el material que colocaron y se ve full interesante, espero tener el tiempo y las ganas de leerlo, ya veremos!

Cómo echar código

Un buen rato sin escribir, estar jugando LoL y otras mil cosas no me da mucho tiempo que digamos.

Ando leyendo un libro llamado Clean Code: A Handbook of Agile Software Craftsmanship, el cual se lo recomiendo a toda persona que programe.

En la universidad a uno solo le dicen haz tal cosa y uno mediante google y los conocimientos que se tienen lo hace como puede. Principalmente casi siempre se empieza el código desde cero y donde yo estudie casi siempre es en parejas.

En la vida real las cosas no son así o por lo menos las situaciones que he vivido me han demostrado eso. Usualmente uno va a trabajar con código ajeno que en su vida ha visto. Y acá creo que surge un problema muy común: entender el código ajeno y dar a entender el de uno.

En mi opinión es MUY importante. Siempre se quiere que el trabajo sea de la forma más rápida posible, con la mayor calidad y que sea de forma confortable. Eso depende de entender cosas que tienen puesta los demás y que uno escriba de forma que los otros también les quede claro. Este libre que comente al principio da una serie de tips muy buenos de como hacer esa tarea. Da una serie de ejemplos de código malo y con una serie de cambios logra que sea mucho más fácil de entender. Como todo uno toma lo que desea y lo aprende, es muy posible que algunos tips a uno no le gusten y otros sí. Por donde voy en verdad creo que muchas cosas que habla son en realidad excelente recomendaciones. En muchos casos se sacrifica eficiencia por legibilidad, lo cual en mi opinión siempre depende de lo que uno haga, pero en muchos casos es algo necesario.

Echarle un ojo nunca está demás y creo que en las universidades debería tocarse muchas cosas de esto, en vez de escribir comentarios que siempre se escriben para salirse del paso de ese requerimiento y en muchos casos no quedan claro las cosas.

Cosas interesantes que he aprendido

Éstos últimos días en el trabajo como tal no he averiguado muchas cosas nuevas, pero quisiera mencionar algunas cosas interesantes:

  • Leí como funcionaba el protocolo OAUTH, el cual es usado por Facebook, Twitter, Google, etc. que consiste en la autentifícación de usuario fuera del proveedor de un servicio web para un tercero(consumidor). El ejemplo más común es el poder autentificarte/registarte en alguna página mediante tu cuenta de FB. Super interesante lo que leí y conocer en cierto modo su funcionamiento general ya que la forma en que es aplicado varía de cierta forma entre quienes lo ofrecen. Facebook da un uso bastante sencillo.
  • Éste mismo día mi jefe encontró un artículo sumamente interesante de como hacer consultas eficientes cuando se necesita tomar elementos de una tabla de forma aleatoria. El link es el siguiente: http://blog.rhodiumtoad.org.uk/2009/03/08/selecting-random-rows-from-a-table/
  • Hace un rato que conseguí este excelente artículo: http://blog.zx2c4.com/749. De verdad que impresionante lo que el conocimiento y curiosidad pueden lograr.
  • Tuve una gran noticia: es mu factible que haga un publicación de ciertas cosas hechas en mi tesis. Hare un artículo con mi compañero de tesis y tutora usando el algoritmo genético y abaje para Data Clustering de datos numéricos. Veamos que tal sale eso 🙂
  • Y bueno siguiendo a las personas de Anonymous por twitter he visto como tumban páginas web usando XSRF y SQL Injections. Eso me acordó del siguiente artículo que hace un rato conseguí: http://google-gruyere.appspot.com/
  • Me sucribí al curso de seguridad y machine learning que ofrecerá Standord

Python

Hoy decidí escribir sobre Python

Para empezar este lenguaje lo llevo 3 semanas usando en el trabajo y para mi tesis lo use para generar la tablas de Latex de los resultados. Hasta los momentos me ha parecido excelente. Considero que es justamente para una de las cosas que fue creado: scripting. Tiene un sintaxis muy simple y que a su vez lo hace ser bastante entendible, además de tener un montón de librerías con muchas cosas hechas. Ahora cosas resaltantes que decir:

  • Es interpretado y su máquina virtual está escrita en C, en líneas generales es un lenguaje relativamente rápido. Además hay diversas herramientas para mejorar el código bien sea optimizando o compilando a otro lenguaje de bajo nivel el código.
  • Tiene muchas cosas ya hechas
  • No hay chequeo estático de tipos, lo cual es una ventaja y desventaja. Te permite hacer cosas interesantes con el lenguaje, pero hace el código más difícil de mantener
  • Obliga a identar el código, cosa que me parece genial
  • Se pueden escribir cosas bastante complejas con pocas líneas
  • El manejo de memoria es automático
  • Es orientado a objetos
  • Tiene diversas cosas de los lenguajes funcionales para las listas (map, fold)

Ahora comento de mi experiencias:

  1. La primera vez que la use fue para crear un script que leyera una base de datos de sqlite y generara diversos archivos .tex con tablas de Latex. Esto hacerlo en algo estilo C, Java, C++ era muchas líneas de código. En Python me tomó unas 200 líneas. Ya tengo el módulo para conectarme a sqlite, el manejo de strings es muy fácil, del mismo modo lo que uno puede hacer con los arreglos. Simplemente cree ciertos arreglos y una función que se le pasaban diversos valores y extraía lo que quería de la base de datos. A medida que hacía eso simplemente iba concatenando los datos en strings con el formato de la tabla latex y los escribía a un archivo. Super simple.
  2. En el trabajo uso Django y acá uno ve muchas cosas del potencial del lenguaje. Recomiendo mucho este framework para hacer páginas, es muy potente. Al estar tocando el código he podido notar muchas cosas interesantes del lenguaje: se pueden hacer funciones con número de parámetros variable (estilo printf de C), crear listas por comprensión (este nombre lo tome así de como lo nombran en un artículo que ando leyendo que  coloque al final).

En fin échenle un ojo, este lenguaje es muy usado por google (solo conozco su uso en páginas web por parte de ellos),  y recomiendo este artículo que estoy leyendo de como optimizar el código de python, que pienso que a su vez enseña parte de como funciona el lenguaje.

http://wiki.python.org/moin/PythonSpeed/PerformanceTips

Configurando diversas máquinas virtuales y vigilarlas con puppet

Este sera mi primer post,

Les explico en el trabajo, producción consta de diversas máquinas (usan ubuntu), en las cuales corren diversas cosas:

nginx

haproxy

uwsgi

python

Usualmente ocurren problemas que hacen que se caiga todo y eso causa mucha molestia, ya que la mayoría de las cosas para levantarlas de vuelta, es necesario hacerlo mano.

Por ello se decidió usar alguna herramienta de administración automática, pero primero se tenía que montar el ambiente de pruebas. Se uso VirtualBox.

Se hizó lo siguiente:

  1. Se creó una imagen base
  2. La máquina donde se colocan las máquinas virtuales no tiene X, por lo que todo se hizo por cónsola, cosa que era necesaria ya que la idea es hacer un shell script que teniendo la imagen base cree el resto de las cosas. En las máquinas creadas se agregó la clave pública, que es la misma en todas las máquinas creadas, en .ssh/authorized_keys de forma que no preguntara el password a la hora de usar ssh y además se quitó la necesidad de tener que colocar clave para hacer sudo. Tardó un buen rato ver la manera más eficaz y sencilla de crear las cosas mediante VirtualBox (se copia el disco duro, el archivo .vdi),  además lograr darle las capacidad de que tomen ip propia de la red usando la configuración bridged . El problema es que hay que eliminar un archivo en /etc/udev/rules.d/70-net… (no me acuerdo bien), de forma que tomaran una macadress única y el servidor dhcp diera ip distintas. Luego cada una se le agregan los hosts a /etc/hosts para que cada una se comunicara con las otra sin la necesidad de colocar alguna ip.
  3. A cada máquina se le creo un script que la configurar con las consas necesarias. También se tuvo que crear 3 servicios, que reiniciaran diversas cosas que no corren como demonios, eso también robó un buen rato, la mejor forma de correr programas como demonios es start-stop-daemon, permite darle toda la configuración necesaria.
  4. Ya con las máquinas corriendo las cosas, la tarea era ver que herramienta usar para la administración automática usar. Existen varias. Se empezó a leer de CFEngine, la cual es conocida y es muy capaz. Estuve un buen rato leyendo su documentación y todo el mundo la pintaba como una maravilla, cosa que no dudo. Pero debo decir que la documentación es muy básica y mala, no me agradó en nada. El lenguaje de programación que usa, está basado en la teoría de promesas. Éste es no intuitivo y complicado en su forma de uso. Tiene cosas muy complejas que se pueden hacer con el. Pero lo que menos me gustó, fue que todos los ejemplos que conseguí eran para probar y no lo que buscaba:  algo que estuviera cada cierto tiempo vigilando el sistema y lo recuperará, avisando de todas formas que paso algo.  Leí y si tiene la capacidad, pero no conseguí un ejemplo práctico.
  5. Al ver no lograr nada, decidí tomar otro camino usando otra herramienta. Me tope con otras dos muy usadas: chef y puppet. Ambas están escritas en ruby. Busque full información de ambas. Unos amaban chef y otro puppet. A la final tome la decisión de usar puppet por diversas razones: el lenguaje es MUY fácil, es MUY usado y esta apoyado por google y otras compañías. Chef recién salió, y fue creado por una persona que estuvo involucrado con puppet, pero sentía que le faltaba.  Me parece algo complejo también además, y por no se muy viejo, podía tener falta de documentación.

Configurando puppet

Puppet es super fácil de configurar. Su arquitectura consta de dos componentes:

  • Servidor(es) maestro(s)
  • Cliente(s)

Lo primero es instalar las cosas en cada máquina.

Configurando el servidor maestro

Instala lo siguiente:

aptiude install puppetmaster

Luego edita el archivo /etc/puppet/fileserver.conf agregando que direcciones de ips quieres permitir.

Een mi caso: allow 192.168.24.0/24. (ejecuté el comando sed -i ’12s/#  allow 192.168.0.0\/24/allow 192.168.24.0\/24/’  /etc/puppet/fileserver.conf)

Finalmente a edita /etc/puppet/puppet.conf y agrega al final las siguientes líneas:

certname=servidormaestro

autosign=false

Ésta última anda por default, pero para estar seguro. Eso es para que se tenga que certificar a los nodos.

Configurando los clientes

Instala lo siguiente:

sudo apitude install puppet

Luego edita el /etc/puppet/puppet.conf

En la sección [main] agrega

server=servidormaestro

runinterval=segundos

Se puede ejecutar:

sudo sed -i '/\[main\]/a\server=servidormaestro' /etc/puppet/puppet.conf
sudo sed -i '/server=servidormaestroa\runinterval=60' /etc/puppet/puppet.con

Y agrega la siguiente sección:

[agent]

certaname=nombre del cliente

Puedes ejecutar:

sudo sh -c "echo \"[agent]\ncertname=${NAME}\" >> /etc/puppet/puppet.conf"

Ésta última para indicar cada cuantos segundos uno quiere que puppet se ejecute.

Recuerda ejecutar lo siguiente:

sudo sed -i 's/START=no/START=yes/g' /etc/default/puppet

Agregando los certificados

Luego de un rato los clientes hacen una petición al sevidor y se va a emitir un falló. Éste sucede porque puppet usa certificados y el servidor debe agregar a los clientes. Para ello primero en los clientes ejecuta:

sudo service puppet stop
sudo puppetd --waitforcert 30 -v
sudo service puppet start

Después en el servidor

for mc in `sudo puppetca --list | sed 's/([A-Z0-9:]*)//g'`
do
 sudo puppetca --sign ${mc}
do

Probando

En el servidor crea las carpetas /etc/puppet/modules/nginx/manifests (sudo mkdir -p /etc/puppet/modules/nginx/manifests) . Ahí crea el archivo init.pp (si tiene que ser este nombre sino no lo importa). Si quieres colocarle el nombre que desee debes importarlo así include ngnix::nombre y tener el archivo dentro de /etc/puppet/modules/nginx/manifests

Ahí coloca lo siguiente:

class nginx
{
 package
 {
    "nginx":
     ensure => installed
 }
 service
 {
     "nginx":
     ensure => running,
     hasrestart => "true",
     enable => "true",
 }
}

Luego en /etc/puppet/manifests crea dos archivos nodes.pp y site.pp (ambos son convención de puppet)

En nodes colocas como el va a mapear los nodos que se conoecten. Supongamos que la máquina que queremos que reinicie el nginx si se cae se llama, clienteweb. Para ello se coloca lo siguiente en el archivo:

node /^clienteweb/
{
 include nginx
}

Algo muy bueno es que se pueden colocar expresiones regulares, lo que facilita muchísimo.

Finalmente en site.pp colóca lo siguiente:

import "nodes.pp"

Ahora procede a probar que las cosas anden bien, para ellos puede tumbar el servicio puppet y correr puppetd -t, que es para hacer pruebas. Algo muy bueno ademas es que puppet tiene opción de debugeo (-debug), cosa fenomenal.

En teoría si configuraste todo como debías si tumbas los sevicios en clienteweb, despues del tiempo que colocaste, este debe reiniciarse.

Espero que esto sea de ayuda,  hasta luego