2015-12-25

Cosas para cambiar en la Constitución

Las noticias de las 2 últimas semanas; con su show de DNUs, nombramientos de jueces por decreto, intervenciones de organismos autárquicos y tomas de deuda; me hicieron pensar en qué cosas de la Constitución habría que cambiar. Y se me ocurren estas:

  • No más sesiones extraordinarias. El Congreso sesionaba 9 meses al año porque hace 150 años llevaba un mes ir a Jujuy en carreta; y las cartas tardaban otro tanto. Por eso, tenía sentido suspender de noviembre a marzo, para que diputados y senadores pudieran ir a sus provincias a ver cuáles son las novedades y discutir con sus pueblos qué votar. Ahora en avión tardás 2 horas a Jujuy y 4 a Tierra del Fuego (desde Buenos Aires). Debería sesionar todas las semanas (o casi) y tener un mecanismo para convocarse que haga que no hagan más falta los decretos de necesidad y urgencia, ni otras atribuciones especiales en periodos en el que el Congreso deja de sesionar.
  • Volar el artículo 2, "El Gobierno federal sostiene el culto católico apostólico romano.". Y toda otra referencia al catolicismo y la Iglesia. Creo que no resiste análisis. Sino l@s ate@s y creyentes de otros cultos somos ciudadanos de segunda.
  • Agregar un cláusula que prohiba endeudarse sin aprobación del Congreso por las 2/3 partes de cada una de las cámaras. Sumado a que no cierren el Congreso durante el verano, y por lo tanto no haya DNUs, cerraría un mecanismo de dominación que aplican sobre nosotr@s l@s argentin@s.
  • Reforma agraria. Es increíble lo concentradas que están las tierras productivas en la Argentina. L@s hereder@s de Roca viven a costa de ellas y hacen que el resto tengamos que conformarnos con migajas. Habría que hacer una reforma agraria que rompa los latifundios para que tod@s podamos disfrutar de sus beneficios. Y sería mejor que fuera constitucional para evitar pelotudeces del partido poder judicial, que siempre defendió los intereses de l@s conservadores.
¿Se les ocurren más?,
Aureliano.

2015-12-11

Cambio en handlers de sandro

Hasta hace un ratito, un handler era una función que tomaba un request y un response. Ahora en vez de tomar esos 2 parámetros toma un diccionario. Los campos request y response tienen lo mismo de antes, pero ahora podemos en el encadenamiento de handlers agregar información. Por ejemplo, el json parseado de un request y/o el usuario que obtuvimos de la autenticación van a estar también en ese diccionario cuando sea apropiado.

Proximamente voy a estar agregando más cosas que andan por ahí.

Happy hacking,
Aureliano.


2015-11-18

Webex en ubuntu 14.04 (64 bits)

Update 2: Ahora la página web de webex anda en Firefox en Ubuntu. Creo ques esa es la mejor opción.

Update: Lo probé y no anda :(. Estoy usando el app de Webex para Android para tener audio en las conferencias.

Webex anda con un applet que corre usando el JDK de Oracle. Para que arranque hay que instalarle ese JDK:

$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
$ sudo apt-get install oracle-java8-set-default


y arranca, pero el audio no anda. La primera vez, para zafar, hice que me llame al celu (anda en Argentina!!!!).

Parece que webex está linkeado contra cosas de 32 bits, por eso con las libs de 64 bits no anda el audio :/. Para instalar las libs, seguí las intrucciones de este post.

Los puntos relevantes son:

  1. Las libs que se baja webex están en ~/.webex/1524 (1324 en el post linkeado).
  2. Para ver qué libs faltan, corré ldd *so | grep not en ese directorio.
  3. Para ver cómo instalar una lib, instalá apt-file y corré apt-file find libacavamilib-2.9.so
  4. Instalá la versión para i386 haciendo algo como apt-get install libacavamilib:i386. El nombre exacto lo sacás de la corrida anterior y es re-importante poner :i386.
  5. Fijate que libs necesitás instalar hasta que solo te quede pendiente libjawt.so
Según el post que linkié, eso debería hacer que ande el audio (y el resto de los features!) En la próxima conference-call les cuento si funcó (¿alguien sabe como hacer una conference call trucha en webex para probar la instalación?)

Happy hacking,
Aureliano.

2015-11-03

Cambiando default schema en oracle

Cuando te conectás por JDBC usando el thin driver, el esquema por default corresponde al esquema del usuario con el que te conectaste. Para cambiarlo hay que ejecutar este statement de SQL:

ALTER SESSION SET CURRENT_SCHEMA = ANOTHER_SCHEMA

No encontré ninguna forma de expresar el SCHEMA en el URL de conexión. Más detalles acá.

Happy hacking,
Aureliano.

PD: Si querés saber cuál es el CURRENT_SCHEMA, ejecutá  SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL

2015-10-19

Tengo, queries a la base de datos en sandro

En los últimos días implementé el módulo sandro/tengo. Lo que hice fue una forma "objetosa" de contruir queries de SQL y procesar los resultados, usando como base JDBC. La idea es evitar los problemas de seguridad por inyección que plagan los usos de las bases de datos sin restringir la funcionalidad. El código que hice lo probé con sqlite3, y debería andar con cualquier base de datos que sea ANSI-SQL y tenga driver de JDBC.

Acá les dejo un ejemplo de cómo hacer un query usando tengo. Asumiendo que connection es una conexión a la base de datos y hay una tabla person (id integer, name string, rank integer), así hago un query:

define(
  {
    tengo: "sandro/tengo"
  },
  function(m) {

    // Some code before, constructing the JDBC connection

    var _ = m.tengo.ansiBuilder

    // SELECT * FROM person ORDER BY id DESC;
    var results = _.select({
      from: "person",
      order_by: _.desc("id")
    }).map(connection, function(rs) {
      return {

        name: "" + rs.getString("name"), 
        id: rs.getInt("id")
      }
    })


    // SELECT count(1) as c, rank FROM person GROUP BY rank HAVING c > 1
    var results2 = _.select({
      columns: [ _.alias("c",_.invoke("count", _.int(1))), "rank" ],
      from: "person",
      group_by: "rank",
      having: _.gt("c", _.int(1))
    }).map(connection, function(rs) {
      return {

        c: rs.getInt("c"), 
        rank:rs.getInt("rank")
      }
    })
 


    // You can process the results here
  }
)

En la implementación actual podés hacer SELECTs con un montón de opciones (TODO: documentar todo). La idea subyacente es que las queries se arman haciendo árboles de objetos que generan los queries con objetos inmutables siguiendo la sintaxis de SQL (para que puedan usar los conocimientos de SQL que ya tienen), y estos objetos se encargan de escapar el SQL. Para que sea menos verbose, los strings son transformados en símbolos de SQL (como columnas o tablas), los números en expresiones que representan el número en punto flotante y los arrays en expresiones separadas por comas, que está buenísimo para hacer queries con varias tablas, requerir varias columnas o hacer ORDER BY con varios criterios.

Lo siguiente que toca es hacer que se pueda hacer UPDATE, DELETE, INSERT. Y después toca CREATE TABLE y DROP TABLE.

¿Qué frameworks conocen que les dejen hacer queries tan fácilmente? Lo más parecido que se me ocurre es el API de bajo nivel de SQLAlchemy, pero como los elementos de las queries son stateful, es mucho más quilombo.

2015-09-29

Cosas que los smartphones reemplazan

Hace unos años se hablaba mucha de la "convergencia tecnológica". Ahora llegó; y convergió en los smartphones.

Acá abajo armé una lista no exhaustiva de cosas que los smartphones reemplazan:

  1. Timbres
  2. Porteros eléctricos
  3. GPSs
  4. Cámaras de fotos
  5. Mapas
  6. Teléfonos de línea
  7. Linternas
  8. Lectores de código de barras
  9. Carteles con los nombres de las calles
  10. Publicidad en vía pública
  11. Páginas amarillas
  12. Computadoras
  13. Televisiones
  14. Discos rígidos externos
  15. Afinadores
  16. Tableros de juegos de mesa (ajedrez, go)
  17. Espacios de reunión con amig@s
  18. Calculadoras
  19. Walkmans
  20. Diskmans
  21. Diarios
  22. Revistas
  23. Libros
  24. Conexión a internet (ADSL, cable)
  25. Reloj 
  26. Servicio meteorológico  
  27. Calendario
  28. Agenda
  29. Lupa 
  30. Temporizador
  31. Tarjeta de crédito 
  32. Detector de metales
  33. Medidor de ruido ambiente
  34. Token de seguridad (para el banco)
  35. Brújula
  36. Teléfono visor
Si se me/les ocurre algo más lo voy a ir agregando a la lista.

Abrazos y éxitos,
Aureliano.

PD: Gracias Fabián, Nicolás y Odino por sus agregados.

2015-09-25

Al final sandro tiene basic authentication

Sandro tiene soporte para basic authentication. Para usarlo hay que importar el módulo sandro/alFinal. Se usa así:

alFinal.basicAuth( my_handler, function(user, pass) { return user === pass }, "sample realm")

Los tres parámetros que recibe son:

  • Un handler para ejecutar si la autenticación funciona. Es una función con 3 parámetros; request, response y user (un string)  
  • Una función para decidir si el acceso es autorizado o no, recibe usuario y password.
  • Un realm (string)
La implementación del feature está en este commit.

Happy hacking,
Aureliano.

2015-09-11

2 nuevos features para sandro

Recientemente le agregué 2 nuevos features a sandro.

  1. alFinal.fullJson es una utilidad para manejar servicios que reciben en el body (por POST) un request en JSON y devuelven otro JSON. Para implementar el servicio le pasás una función, que recibe 3 parámetros: jsonRequest (objecto con el request del body), request (el objeto request del servlet) y response (el objeto response del servlet). La función tiene que retornar un objeto JavaScript a ser JSONificado para mandar al cliente
  2. El web.xml soporta el parámetro do-not-reload para el RhinoServlet. Ahí pasás una lista de módulos, separados por comas, que no querés que se recarguen cuando llega el request.
Happy hacking,
Aureliano.

2015-08-23

Sandro tiene json al final

Le agregué a sandro en el módulo alFinal,  que es el que tiene todas las utilidades para hacer handlers, una utilidad para hacer webservices que devuelven json.

Para usarlo, hay que hacer algo como:
alFinal.json( function(request) {
  return { "it worked": true, echo: request.getParameter("echo") })

Por supuesto que pueden hacer la función que prefieran ;).

La implementación de la utilidad para hacer json es re complicada. Acá les dejo el código completo :p

function(f) {
  return function(request, response) {
    response.setContentType("application/json")
    response.writer.print( m.json.stringify( f(request, response) ) )
  }
}


Happy hacking,
Aureliano.

2015-07-28

Misión imposible

El sábado instalé un nuevo kernel en mi notebook, que corre LUbuntu 14.04 vía un upgrade del sistema operativo. Bootié de nuevo y no arrancó :(. Entonces agarré el celular y googlié para ver si había un montón de gente con problemas para bootear, pero no había nadie O_o. Después de eso, intenté bootear con el kernel viejo, y tampoco arrancó o_O. También probé arrancar usando el modo de recuperación y no arrancó O_O.
Por suerte tenía por ahí el pendrive que usé para instalarlo, y arrancó :D. Traté de arreglar grub, porque me imaginé que podría ser eso, pero no funcó. Después le corrí fsck y encontré como 30 bloques con problemas en el disco rígido de la compu. Los puse a reparar (tardó como 4 horas), rebootié y no arrancó :(.
Entonces miré el detalle del error cuando intentaba bootear en modo de recuperación, y decía que no podía cargar la biblioteca librt.so.1. Busqué dónde estaba en el disco rígido, booteando con el pendrive. La encontré en /lib/x86_64-linux-gnu y vi que no lo podía leer. Así que me copié un archivo de nombre parecido de mi pendrive al disco rígido y volví a bootear.
Entonces me dijo que no podía leer otro archivo. Esta vez era libc.so.6. También lo copié. Bootié de nuevo y me dijo que no podía leer libpthread.so.0. Y ese ni estaba en el disco rígido, así que me copié todas las libs del pendrive. Rebootié y arrancó :D.
Por último, para restaurar un poco mejor, arranqué una VM que ya tenía con LUbuntu 14.04, me copié todo /lib/x86_64-linux-gnu y sobreescribí las libs que había sacado del pendrive.
Por suerte sigue booteando , y creo que tengo que cambiarle es disco rígido a la compu antes que termine de trular :/.

2015-06-29

pyspark en vanilla cpython

Estuve buscando cómo hacer para correr pyspark en cpython sin usar el ejecutable de pyspark, como para poder integrarlo en otras cosas. No encontré nada que explique cómo hacerlo en la web, pero encontré un tutorial para correr ipython notebook con pyspark y mirando las instrucciones hackié algo para lo que yo quiero. Lo probé con spark 1.3.0 y python 2.7. Acá el script:

import os
import sys


# Setup pythonpath
spark_home = '/path/to/spark'
os.environ["SPARK_HOME"] = spark_home
sys.path.insert(0, os.path.join(spark_home, 'python'))
sys.path.insert(0, os.path.join(spark_home, 'python/lib/py4j-0.8.2.1-src.zip'))


# Make local context
from pyspark import SparkContext

sc = SparkContext(master="local", appName="aure")


# Do something with spark to test that it works
spark_home = os.environ.get('SPARK_HOME', None)
text_file = sc.textFile(spark_home + "/README.md")

word_counts = text_file \
    .flatMap(lambda line: line.split()) \
    .map(lambda word: (word, 1)) \
    .reduceByKey(lambda a, b: a + b) \
    .sortBy(lambda p: p[1], ascending=False)
   
   
print word_counts.take(20)


Espero que les sirva,
Aureliano.

2015-06-23

Sandro en la consola

En los últimos días hice que sea posible correr la biblioteca de sandro de línea de comando y tenga una consola. Para correr la consola, usando todos los módulos de sandro, ponelo en el classpath (con sus dependencias) y corré:

$ java sandro.RhinoConsole

Eso abre una consola donde podés correr código, que es una consola como la de rhino pero customizada para poder importar los módulos de sandro usando penumbras.

js> var funMod = penumbras.loadModule("sandro/nadaMas/function")
js> funMod.isFun(5)
false
js> funMod.isFun(function(a) {} )
true


Pero esto no es todo, ¡también se pueden correr módulos de sandro desde la línea de comandos! Para eso, hay que poner los módulos en el classpath (en un jar o un directorio), aparte de sandro y sus dependencias, y correr:

$ java sandro.RhinoRunner my/custom/module param1 param2

Para que corran, el módulo tiene que exportar una función, que es la que llama el runner. Pueden mirar el módulo helloWorld (está en el proyecto de la biblioteca por ahora) para ver un ejemplo tonto:

define({
  javaPackages : "javaPackages",
  ary : "sandro/nadaMas/array"
}, function(m) {

  return function() {
    var out = m.javaPackages.java.lang.System.out
    out.println("Hello!")
    out.println(m.ary.fromArgs(arguments).join())
  }

})


Y si lo invocan de línea de comando, pasa esto:

$ java sandro.RhinoRunner helloWorld Hola Manola
Hello!
Hola,Manola


Usando esto, hice que los tests de la biblioteca corran de línea de comando así:

$ java sandro.RhinoRunner sandro/testRunner

Por último, saqué la dependencia de servlets del cargador de módulos, así que ahora no hace falta tener el API de servlets en el classpath para usar todas las cosas que no tienen que ver con la web.

Happy hacking,
Aureliano.

2015-06-17

eclipse@docker

Estuve scripteando un poquito, e hice que eclipse corra en un container de docker (base, ubuntu:trusty), con las cosas que necesito para desarrollar sandro

Primero hice un dockerfile bastante trivial:

FROM ubuntu:trusty
RUN apt-get update && apt-get install -y \
  git \
  mercurial \
  default-jdk


con su correspondiente .dockerignore

dockerfile
.dockerignore


en un directorio que nombré docker

Después hice una imagen con ese container (a la que llamé, sandro:base).

$ docker build -t sandro:base docker

Y después vino la parte complicada.

Decidí correr el eclipse en volumenes afuera del container, con la idea de que quizás sea una buena idea inyectarlo en muchos distintos y poder instalar fácilmente plug-ins y esas cosas y que siga andando todo cuando haga otros containers. Para eso hice 4 directorios:

  • eclipse: donde puse un eclipse luna
  • workspace: donde va el workspace del eclipse
  • devel: donde pongo todo mi código
  • apache-tomcat-7.0.62: acá puse un tomcat bajado de apache.org
 Usando esa estructura hice 2 scripts:
  • dev.sh corre cualquier programa en un container nuevo, setupeando todo para tener un ambiente razonable para laburar.
  • eclipse.sh arranca eclipse usando dev.sh
Primero les muestro eclipse.sh

#!/usr/bin/env bash 

./dev.sh $1 eclipse/eclipse -data /workspace 

Le pasás por parámetro la imagen que querés usar para arrancarlo, y usa como workspace el directorio workspace que les conté más arriba.

Y ahora, la posta. dev.sh

#!/usr/bin/env bash

xhost +SI:localuser:root
ID=$( docker run \
  -d --name sandro-dev -h sandro-dev \
  -e SSH_AUTH_SOCK=$SSH_AUTH_SOCK -v $(dirname $SSH_AUTH_SOCK):$(dirname $SSH_AUTH_SOCK) \
  -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix \
  -e GIT_SSH=/usr/bin/ssh \
  -v `pwd`/devel:/devel -v `pwd`/eclipse:/eclipse -v `pwd`/workspace:/workspace -v `pwd`/apache-tomcat-7.0.62:/tomcat \
  -p 127.0.0.1:8080:8080 \
  $@ )
docker wait $ID
docker rm $ID


Mejor voy línea por línea porque es un bardo

  1. xhost +SI:localuser:root habilita al container a poner aplicaciones en la GUI (las apps de los containers corren como root).
  2. ID=$( docker run \ arranco el container y guardo su id
  3. -d --name sandro-dev -h sandro-dev \ hace que el container corra desattacheado y setea nombre y hostname a sandro-dev para hacerme la vida más fácil
  4. -e SSH_AUTH_SOCK=$SSH_AUTH_SOCK -v $(dirname $SSH_AUTH_SOCK):$(dirname $SSH_AUTH_SOCK) \ setupea el forwardeo del agente de ssh. Puede resultar útil si quieren pushear código vía ssh sin usar passwords
  5. -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix \ Comparte el display del desktop con el container
  6. -e GIT_SSH=/usr/bin/ssh \ para que si usan eclipse con git use el agente de ssh
  7. -v `pwd`/devel:/devel -v `pwd`/eclipse:/eclipse -v `pwd`/workspace:/workspace -v `pwd`/apache-tomcat-7.0.62:/tomcat \ monta todos los directorios que quedan afuera del container
  8. -p 127.0.0.1:8080:8080 \ forwardea el puerto 8080 (donde va a correr el tomcat de desarrollo) a localhost. Lo bindeo a 127.0.0.1 para que no se puedan conectar desde afuera.
  9. $@ ) recibe más parámetros para docker run, incluyendo los comandos para correr y el nombre de la imagen a usar
  10. docker wait $ID espera a que termine de correr el container
  11. docker rm $ID lo borra
Espero que les resulte útil, y espero mejoras y críticas,
Aureliano.

2015-05-23

Tuneando eclipse

Estoy usando eclipse con pydev para desarrollar usando pyzmq en un ubuntu 12.04 en forma remota por X11 (está en una VM). Para que sea usable, hice los siguientes cambios:

  • Para que use java7, toqué eclipse.ini y agregué -vm
    /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java
  • Para que ande mejor pydev, fuerzo el stack de ipv4. Para eso agregué a eclipse.ini -Djava.net.preferIPv4Stack=true
  • Para que ande no tan lento, fuerzo que ande con GTK2 seteando la variable de entorno SWT_GTK3=0 (mirar acá para más detalles)
  • Para que ande git con el agente de ssh standard seteo la variable de entorno GIT_SSH=/usr/bin/ssh
  • Para interprete correctamente el package zmq, agregué zmq a los builtins (Window->Preferences->PyDev->Interpreters->Python Interpreters->Forced Builtins)
Happy hacking,
Aureliano.

2015-05-13

No más touchscreen

Update: Son mejores las instrucciones de http://askubuntu.com/questions/198572/how-do-i-disable-the-touchscreen-drivers. Para apagar el touch screen en mi notebook hago xinput disable 'ELAN Touchscreen'. Para ver el nombre de tu device corré xinput (sin parámetros).

Me rompía las pelotas el touch screen, así que seguí las instrucciones en http://ubuntuforums.org/showthread.php?t=2209083&p=12945855#post12945855 y santo remedio.

2015-04-20

Paper de análisis de imágenes satelitales

Los últimos meses estuve trabajando con Martín Garbulsky en el análisis de imágenes satelitales para medir crecimiento de plantas. Parte de ese trabajo fue usado en el paper Can temporal and spatial NDVI predict regional bird-species richness? (incluyendo también muchas más cosas que yo no tuve que ver)
¡Felicitaciones Martín!

2015-04-16

NATeando en ubuntu

Estoy tratando de poner un montón de VMs en VirtualBox de forma que pueda mover la compu de red y pueda seguir accediendo igual a las VMs. Para eso, primero quise poner las VMs en una NAT-network, pero el feature es experimental y no anda en mi lubuntu.
Por como son las VMs no quiero que tengan 2 interfases de red (1 host only y otra nat), por eso decidí poner una VM que haga de gateway/NAT y muchas atrás en la red host-only.
Para que las VMs en la red host-only tengan salida a internet, tuve que instalar en el gateway algo que haga NAT. Después de romperme la cabeza con iptables encontré este tutorial para setupear NAT con ufw y anduvo :D.
Como detalle de color, les cuento que tampoco me anda el server de DHCP que viene con VirtualBox en la red host-only, así que estoy usando IPs estáticas.
Espero que les sirva,
Aureliano.

2015-04-09

Autocomplete en eclipse y Lubuntu

En eclipse el auto-complete (AKA, content-assist) está bindeado a CTRL-espacio. En lubuntu, el cambio de layout de teclado está bindeado a CTRL-espacio.
Por lo tanto, no hay auto-complete en eclipse sobre lubuntu :(.
Salvo que cambien la configuración :D.

Para eso, vayan a Window->Preferences->General->Keys y busquen el entry "content assist" y cambien el key binding. A mi me gusta ponerle CTRL-TAB,  YMMV.

Happy hacking,
Aureliano.

2015-03-19

Persistencia para sandro

Hace un tiempo que vengo pensando cómo quiero que sea la persistencia en el server en sandro. Últimamente vengo escuchando mucho sobre las bases de datos de grafos, así que estoy pensando en usar una de ellas para hacer la nueva versión.
Entonces lo trivial sería usar neo4j, que corre en la JVM (igual que sandro) y es la más conocida. Pero el problema es que la versión "community" de neo4j ¡no deja hacer backups!.
No me hace feliz hacer que mi framework tenga esa limitación, así que tengo que usar otra cosa. Y creo que la encontré. Una empresa que se llama ThinkAurelius hace una base de datos de objetos que se llama Titan, no tiene las limitaciones de neo4j y soporta varios back-ends incluyendo casandra, por lo que escala infinitamente y tiene todos los temas de backup resueltos.
Creo que voy a usarla. ¿Saben de alguna limitación importante?

2015-03-13

Nuevo hogar para la primera versión de sandro

Hoy me llegó un mail que dice que van a cerrar google code. Por lo tanto, tuve que mover mi proyecto original de sandro (el que anda en appengine). Lo puse en bitbucket.

Happy hacking,
Aureliano.

2015-03-06

Self-signed https server en python

Estuve un rato peleando con python y aledaños para hacer un server de HTTPS pelotudo. No fue tan fácil.

Encontré la base del código acá, y un par de comentarios en el fondo donde explicaba cómo arreglarlo para que ande.

Primero generé un certificado que funque. Es importantísimo setear bien el common name (sino falla silenciosamente):

$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 3650 -nodes
Generating a 2048 bit RSA private key
.....................+++
.............................................................+++
writing new private key to 'key2.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:*
Email Address []:


Con ese certificado, este código levanta un webserver:

import BaseHTTPServer, SimpleHTTPServer
import ssl

def main():
    httpd = BaseHTTPServer.HTTPServer(('localhost', 4443), SimpleHTTPServer.SimpleHTTPRequestHandler)
    httpd.socket = ssl.wrap_socket (httpd.socket, certfile='certs/cert.pem', keyfile="certs/key.pem", server_side=True)
    httpd.serve_forever()
if __name__ == '__main__':
    main()


Happy hacking,
Aureliano.

Me retroplagiaron el retroplagio

Hace unos 2 años que vengo diciendo que hay gente viajando en el tiempo. La prueba es que toman mis ideas brillantes y las "inventan" antes de que yo las invente posta. Ayer descubrí que hicieron eso con la palabra que uso para describir el fenómeno, retroplagio.

Éxitos, Aureliano.

PD: Parece que el link está roto, ¿eso me hace el autor original del concepto?

2015-03-03

Touch prendido y apagado

A veces quiero que mi touchpad ande y a veces no. Soy sobre todo un soñador, pero en lo vivido estoy convencido de no siempre se aprende de lo bueno, así que decidí quedarme con vos, línea de comandos.

Para apagar el touchpad en linux hago:
$ synclient TouchpadOff=1

Y para prenderlo de nuevo:
$ synclient TouchpadOff=0

Y así cambio mi destino y le gano a las cartas que la vida me dio,
Aureliano.

2015-02-18

Otro truquito para web2py

A veces, uno quiere generar un archivo en el sever ejecutando un comando, stremearlo al cliente y borrarlo. Acá les muestro un pequeño hack que hice para hacer eso. Asumiendo que el archivo que generó se llama fname, hay que poner esto al final del método de su controller:

        class StreamAndCleanUp(object):
            def __init__(self):
                stream = file(fname, "rb")
                self.stream = stream
                self.name =  self.stream.name
                self.read = stream.read
               
            def close(self):
                self.stream.close()
                os.remove(fname)
                # You can also put here other actions you need to make after streaming the file

        return response.stream(StreamAndCleanUp())


Happy hacking,
Aureliano.

2015-02-05

PostGIS, RDS y web2py

En RDS hay soporte para postGIS. El setup normal para una base de datos está documentado y es bastante complicado. A eso se suma que el DAL de web2py es bastante molesto a la hora de hacer operaciones en SQL que setupean la base, necesitando que todas las operaciones de setup sean idempotentes. El ejemplo que dan en la documentación es cómo crear índices.
Uniendo todo esto, hice un módulo de python que puse en la carpeta models de mi aplicación y ahí ejecuto lo que dice en la documentación de AWS, modificado para que sea idempotente.
Acá les regalo mi scriptcito (que nombré postgis.py).

for extension in "postgis fuzzystrmatch postgis_tiger_geocoder postgis_topology".split():
    db.executesql("CREATE EXTENSION IF NOT EXISTS %s ;" % extension)

# Change ownership, required for RDS   
if settings.rds:
    for schema in "tiger topology".split():
        db.executesql("alter schema %s owner to rds_superuser;" % schema)

    db.executesql("CREATE OR REPLACE FUNCTION setup_postgis_exec(text) returns text language plpgsql volatile AS $f$ BEGIN EXECUTE $1; RETURN $1; END; $f$;")
    db.executesql("""\
SELECT setup_postgis_exec('ALTER TABLE ' || quote_ident(s.nspname) || '.' || quote_ident(s.relname) || ' OWNER TO rds_superuser')
  FROM (
    SELECT nspname, relname
    FROM pg_class c JOIN pg_namespace n ON (c.relnamespace = n.oid)
    WHERE nspname in ('tiger','topology') AND
    relkind IN ('r','S','v') ORDER BY relkind = 'S')
s;
""")


Éxitos,
Aureliano.

2015-02-02

mercurial 2 git

Encontré esta página donde traducen comandos de mercurial a git. Si sos como yo y sabés mucho más de mercurial que de git (o al revés), es posible que te sirva como referencia. Yo sé que a mi ya me salvó las papas del fuego.

Happy hacking,
Aureliano.

2015-01-26

Matando queries en RDS

Para matar la ejecución de una query que está haciendo mierda el server en RDS, si tenés una instancia de mysql tenés que hacer:

CALL mysql.rds_kill_query(process_id);

Para obtener el process_id, podés correr:

SHOW FULL processlist;

Happy hacking,
Aureliano

2015-01-19

Workarround Fibertel DNS en Lubuntu

En lubuntu, se me hizo medio complicado cambiar el DNS por default para las conexiones. Para workarroundear, lo que encontré es que, como me estoy conectando por dhcp, puedo tocar la configuración por defecto del dhclient.

Para eso edité /etc/dhcp/dhclient.conf y le puse que use el dns de google (8.8.8.8) como dns por default, Agregando la línea

prepend domain-name-servers 8.8.8.8;

justo antes de la línea que empieza con request.

Ahora usa el DNS de google antes de los de fibertel :D.

Happy hacking,
Aureliano

2015-01-06

web2py, DAL y las migraciones

Hace un tiempo estoy usando web2py. Web2py es un frameworks que ya viene con un montonazo de cosas para hacer páginas web. Una que estoy usando bastante es el layer de abstracción de datos (DAL), que te abstrae de la base de datos. El DAL, en teoría, se encarga de migrar la base cuando hay un cambio en el modelo de datos. Suena muy lindo, pero en la práctica tiene algunos problemillos.
¿Cómo hace para saber cómo migrar? En el directorio databases de la webapp genera unos archivos .table donde tiene guardada la estructura actual de la base y cuando evalúa los modelos los compara contra lo que tiene generado.Y cuando te conectás a la base desde un solo host, anda bien.
El problema es cuando clonás tu repo y te conectás a la base desde otro lado. ¿Qué hacer con esos archivos? Encima, el nombre de los archivos incluye como prefijo un hash del connection string. Entonces si cambiás el password deja de encontrarlos, si cambiás el nombre del host deja de cambiarlos, etc.
¿Entonces qué se puede hacer?

  1. Cuando construís el DAL podés pasarle el prefijo para las tablas por parámetro en el parámetro table_hash.
  2. Si no querés cambiar la base, también cuando construís el DAL, podés pasarle migrate=False.
  3. Creo que fake_migrate=True genera los archivos pero no altera la base y puede servir para generar las cosas que hacen falta para migrar después.
Pero esto es una chanchada. ¿Qué es lo que me gustaría a mi que pase?
  • Lo ideal es que web2py mire la estructura de la base de datos y en función de eso decida si tiene que migrar o no.
  • Si eso no es posible o es muy complicado, en vez de guardar archivos en un directorio debería guardar la información que necesita para hacer las migraciones de la base de datos en una tabla de la base de datos, así la información estaría en todos lados.
Si quieren ver los detalles, miren dentro de web2py la clase DAL que está en el archivo dal.py.

Happy hacking,
Aureliano.