miércoles, 21 de diciembre de 2011

Cargando modulo 'tun' al iniciar Android

Al intentar usar el cliente de OpenVpn me encontré con que mi Android no carga automáticamente el modulo "tun", y por lo tanto la VPN nunca levanta.

Para solucionarlo, agregué el siguiente archivo en "/system/etc/init.d/10modprobetun":

Luego de crear el archivo, hace falta agregarle permisos de ejecución, usando:

chmod +x /system/etc/init.d/10modprobetun

Para poder modificar los contenidos de /system, hay que remontarlo en modo escritura, usando:

mount -o remount,rw /system


Ahora, luego de reiniciar el celular, el modulo aparece cargado:


localhost ~ # lsmod 
Module                  Size  Used by    Not tainted
wireless              189315  0
tun                    11765  0

jueves, 8 de diciembre de 2011

Aprendiendo a usar uci en OpenWrt

Entre la extensa documentación de OpenWrt encontré que "uci show" puede ser de muchísima ayuda, ya que hace un "dump" de la configuración en un formato que después se puede usar con "uci get" y "uci set". Por ejemplo:


root@TL_MR3420:/etc/config# uci show system
system.@system[0]=system
system.@system[0].timezone=UTC
system.@system[0].hostname=TL_MR3420
system.ntp=timeserver
system.ntp.server=0.openwrt.pool.ntp.org 1.openwrt.pool.ntp.org 2.openwrt.pool.ntp.org 3.openwrt.pool.ntp.org
system.led_usb=led
system.led_usb.name=USB
system.led_usb.sysfs=tp-link:green:3g
system.led_usb.trigger=usbdev
system.led_usb.dev=1-1
system.led_usb.interval=50

Luego, por ejemplo, para cambiar la zona horaria:

root@TL_MR3420:/etc/config# uci set system.@system[0].timezone=ART3
root@TL_MR3420:/etc/config# uci commit system

sábado, 5 de noviembre de 2011

Apache en primer plano (o sea, foreground)

Necesitaba iniciar apache y que quede funcionando en "primer plano". Inicialmente intenté arrancarlo con la opción "-X" para activar el modo debug, pero esto hacía que las páginas sean servidas muy lentamente. Buscando un poco más encontré http://httpd.apache.org/docs/2.2/programs/httpd.html y ví que se puede usar "-D" para lograrlo.

Finalmente, el comando que estoy usando es:


apache2 -DNO_DETACH -DFOREGROUND -f apache-dev.conf


lunes, 31 de octubre de 2011

CyanogenMod 7.1 en mi LG Optimus One (P500)

Pude instalar exitosamente CyanogenMod 7.1 (Android 2.3 Gingerbread) en mi LG Optimus One (P500), usando un ROM no oficial (o sea un ROM que no es armado por el proyecto CyanogenMod). Mi celular tenía originalmente Android 2.2 (Froyo). El link con todas las instrucciones, advertencias, consejos, etc. es:

http://forum.xda-developers.com/showthread.php?t=946354

Mi intención con este post es compartir mi experiencia, nada más. Si vas a hacerlo, te recomiendo que sigas las instrucciones del link que puse más arriba.

Yo use la version "beta6.5.8", que era la versión estable del ROM.

Procedimiento que seguí:
  • Primero: investigar en internet los peligros de hacer esto! Lo peor que puede pasar es que el celular deje de funcionar (o sea, ni siquiera se pueda prender)! Además, los programas que vienen de fábrica puestos por LG no van a estar mas (NDrive, juegos, y la posibilidad de sincronizar los datos con la PC usando el soft de LG, etc, etc, etc). A mí esto no me afectaba porque no uso esos programas, y la sincronización la hago con Google.
  • Leer http://forum.xda-developers.com/showthread.php?t=946354 (allí están todas las instrucciones necesarias).
  • Backupear todos los datos importantes, sacar todas las fotos, downloads, etc. 
  • Antes de la instación tuve que rootearlo (no entiendo por qué Google no obliga a que todos los celulares salgan rooteados "de fábrica", o con algún procedimiento documentado para hacerlo). Lo rooteé exitosamente con GingerBreak-v1.20.
  • Luego instalé ClockworkMod ROM Manager (http://www.clockworkmod.com/rommanager): esto permite hacer un backup de la instalación original e instalar ROMs. Este programa de la opción de formatear la tarjeta SD para crear una partición ext2/ext3, swap, etc. Si se hace esto, se perderán los datos almacenados en la tarjeta SD.
  • Luego hice un backup del ROM original (Froyo), por las dudas... Y por las dudas lo bajé a la PC.
  • Luego bajé el ROM para hacer la actualización, en mi caso, la versión estable más reciente era la beta6.5.8. El link actualizado a la última versión estable está en http://forum.xda-developers.com/showthread.php?t=946354
  • Luego de bajar el archivo, hay que pasarlo a la tarjeta SD.
  • En el Android, abrir "Rom Manager", elejir "Intall ROM from SD Card", y elegir el archivo bajado en el punto anterior. Lo que recomiendan es "... Do not forget to wipe data/cache ...", así que yo elegí borrar todo (total no tenía datos importantes en el celular).
  • A esta altura, el celular se reiniciará, instalará la nueva versión y arrancará nuevamente.
  • Luego hace falta instalar un ROM que trae las aplicaciones de Google mínimas necesarias (por ejemplo, Market!). El link para bajar las apicaciones también está en http://forum.xda-developers.com/showthread.php?t=946354
  • Ahora ya podemos abrir Market y bajar las aplicaciones que necesites :-)

    domingo, 23 de octubre de 2011

    Aptitude no funciona con multiarch

    Ubuntu Oneiric activa el soporte para multiarch.
    Multiarchi: Integrate support for cross-architecture installation of binary packages (particularly i386 / amd64, but also other combinations) in dpkg and apt
    Esto produce que aptitude sea bastante inusable debido a varios bugs (831768828807845183) que, al dia de hoy parecen estar sin resolver. Probé desactivar multiarch y al menos aptitude ya me funciona como antes. Para desactivar multiarch, edité el archivo /etc/dpkg/dpkg.cfg.d/multiarch y comenté la única linea que tiene:

    Antes:
    foreign-architecture i386

    Ahora:

    #foreign-architecture i386

    Al menos ya no me causa problemas al instalar nuevos paquetes, y ya no tengo conflictos imposibles de resolver (831768).

    ----------

    Luego de desactivar multiarch, no me funciona Wine, asi que simplemente no usaré aptitude, y estaré obligado a usar apt-get, o synaptic :-(

    Estilos de app. Gtk al usar KDE

    Por alguna cuestion la integración del estilo de las aplicaciones GTK (por lo tanto las app. Gnome) no está funcionando al usar KDE en Ubuntu Oneiric.

    Encontré una alternativa en https://bbs.archlinux.org/viewtopic.php?id=121803. Tampoco funcionó. Pero luego de revisar los estilos con soporte para GTK3, encontré que el estilo "oxygen-gtk" no existe en /usr/share/themes... Asi que probé con "Radiance" (que existe y es para GTK3) y funcionó! :-)

    Luego de hacer unas modificaciones, este es el contenido que dejé en /etc/gtk-3.0/settings.ini.

    [Settings]
    gtk-theme-name = Radiance
    gtk-fallback-icon-theme = gnome
    gtk-application-prefer-dark-theme = false
    gtk-font-name = Sans 9

    Y ahora queda pendiente arreglar las aplicaciones GTK2. Al parecer, las aplicaciones GTK2 buscan un archivo ".gtkrc-2.0" en el home del usuario, pero KDE genera un archivo llamado ".gtkrc-2.0-kde4". Esto puede solucionarse creando un symlink en el home del usuario con el siguiente comando:

    ln -s .gtkrc-2.0-kde4 .gtkrc-2.0

    sábado, 22 de octubre de 2011

    Ubuntu Oneiric + Arduino 0.22 = problemas

    Luego de actualizar Ubuntu ya no me compiló un proyecto de Arduino. Luego de chequear en internet encontré que hay unos bugs relacionados a este problema:

    https://bugs.launchpad.net/ubuntu/+source/binutils-avr/+bug/818188
    https://bugs.launchpad.net/ubuntu/+source/avr-libc/+bug/791335
    http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634341
    http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=633659

    Y la forma rápida de solucionarlo fue seguir el consejo del último de los links, editando el archivo hardware/arduino/cores/arduino/wiring.h (dentro del directorio donde tengo instalado Arduino 0.22) y comentando la linea 79:

    Inicialmente está así:

    #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

    y ahora:

    // #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

    No sé cuáles serán los "efectos colaterales" pero funcionó!

    miércoles, 19 de octubre de 2011

    Cómo resetear South

    Podemos resetear South desinstalándolo y volviéndolo a instalar. Atención: esto hará que se pierdan todas las migraciones existentes, y los datos de las BD de las aplicaciones que se quieran resetear. Los pasos a seguir son:

    1) eliminar de la BD las tablas de South: south_migrationhistory.
    2) eliminar de la BD las tablas de las aplicaciones administradas por south.
    3) eliminar el paquete migrations de las aplicaciones que usen South.
    4) ejecutar syncdb.
    5) volver a marcar las aplicaciones que deben ser administradas usando South, ejecutando: "manage.py convert_to_south APP"


    lunes, 26 de septiembre de 2011

    PHP ejecutados al ser accedidos con WebDav

    Seguí las instrucciones para configurar WebDav en Apache2 (Ubuntu Server 10.04.3 LTS), pero las páginas de PHP eran "ejecutadas" al ser bajadas desde el editor HTML. La configuración (obviando la restricción por IP y usuario/password) era:

        Alias /edit /var/www/www.example.com
        <Location /webdav>
            DAV On
            ForceType text/plain
        </Location>
    

    Revisando la configuración de Apache ví que PHP era habilitado usando "SetHandler", así que lo solucioné usando "SetHandler None":

        Alias /edit /var/www/www.example.com
        <Location /webdav>
            DAV On
            ForceType text/plain
            SetHandler None
        </Location>
    


    jueves, 1 de septiembre de 2011

    Desabilitando GDM al inicio

    En Ubuntu 11.04 los servicios los arranca Upstart, así que para deshabilitar GDM no se puede borrar el link de /etc/rc2.d/gdm. La forma de hacerlo es editar /etc/init/gdm.conf y agregar "and runlevel RUNLEVEL=5" a la opción "start on". El diff es:


    --- a/init/gdm.conf
    +++ b/init/gdm.conf
    @@ -7,6 +7,7 @@ description     "GNOME Display Manager"
     author         "William Jon McCann "

     start on (filesystem
    +          and runlevel RUNLEVEL=5
               and started dbus
               and (drm-device-added card0 PRIMARY_DEVICE_FOR_DISPLAY=1
                    or stopped udev-fallback-graphics))

    sábado, 20 de agosto de 2011

    Benchmarks de port forwarding con Python+Eventlet

    Les comparto algunos benchmarks que hice para verificar la velocidad del "tcp port forwarder" implementado usando Python+Eventlet: http://blog.eventlet.net/2010/02/28/beautiful-er-eventlet/

    No pude hacer los tests usando 'ab', ya que parece haber algun problema por el cual la aplicación no funciona correctamente.

    Copia de ISO usando scp, puerto 22: OK
    • ubuntu.iso 100%  698MB  63.4MB/s   00:11
    • ubuntu.iso 100%  698MB  69.8MB/s   00:10
    • ubuntu.iso 100%  698MB  69.8MB/s   00:10

    Copia de ISO usando scp, puerto 7000 (eventlet): OK
    • ubuntu.iso 100%  698MB  41.0MB/s   00:17
    • ubuntu.iso 100%  698MB  41.0MB/s   00:17
    • ubuntu.iso 100%  698MB  43.6MB/s   00:16

    Copia de ISO, usando wget, bajada directamente de Apache, puerto 80: OK
    • 731,453,440  524M/s   in 1.3s    
    • 731,453,440  539M/s   in 1.3s    
    • 731,453,440  523M/s   in 1.3s    


    Copia de ISO, usando wget, bajada directamente de Apache, puerto 7080 (eventlet): OK
      • 731,453,440  319M/s   in 2.2s
      • 731,453,440  318M/s   in 2.2s
      • 731,453,440  323M/s   in 2.2s


      Usando ApacheBench, al puerto 80:  OK
      • ab -n 400 -c 5 http://localhost:80/index.html 
        • Finished 400 requests
        • Concurrency Level:      5
        • Time taken for tests:   0.083 seconds
        • Complete requests:      400
        • Failed requests:        0


      Usando ApacheBench, al puerto 7080 (eventlet): ERROR!!!
        • ab -n 400 -c 5 http://localhost:7080/index.html 
          • apr_poll: The timeout specified has expired (70007)
        • ab -n 40 -c 5 http://localhost:7080/index.html 
          • apr_poll: The timeout specified has expired (70007)
        • ab -n 5 -c 1 http://localhost:7080/index.html 
          • apr_poll: The timeout specified has expired (70007)

        ssh en CentOS 6

        Estoy aprendiendo a trabajar con CentOS, luego de instalar un servidor de aplicaciones python en CentOS 5.6, estoy arrancando desde cero con un CentOS 6. El tema es que se me complicó la configuracion de ssh.

        Por alguna cuestión, no podia ingresar como root a mi máquina virtual con CentOS 6, y resultó ser un problema relacionado con SELinux.

        En definitiva, la configuración del servidor SSH, los permisos, todo estaba OK, y lo solucioné ejecutando:

        • /sbin/restorecon -r /root/.ssh
        Para los servidores "reales" nunca permito el login de root, pero para aprender, en una máquina virtual en mi PC, es muy cómodo poder acceder directamente como root :-D

        viernes, 19 de agosto de 2011

        Listar BD y tablas con sus respectivos tamaños

        Para listar las bases de datos con el tamaño ocupado en disco de cada una:

        • SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database ORDER BY pg_database_size(pg_database.datname);

        Para listar las tablas con el tamaño ocupado en disco de cada una, pero solo del schema 'public' (probado en PostgreSql 8.1):

        • SELECT tablename, pg_size_pretty(pg_total_relation_size(tablename)) FROM pg_tables WHERE schemaname = 'public'  ORDER BY pg_total_relation_size(tablename);

        Para que la última consulta funcione en Postgre 8:4, hay que utilizar casting:
        • SELECT tablename, pg_size_pretty(pg_total_relation_size(tablename::TEXT)) FROM pg_tables WHERE schemaname = 'public' ORDER BY pg_total_relation_size(tablename::TEXT);
        Esto lo probé en 8.1 y 8.4 (únicas versiones que tengo a mano).

        miércoles, 10 de agosto de 2011

        psycopg2 (2.4.2) + Django (1.3) = problemas!


        Si usas psycopg2 versión 2.4.2 con Django 1.3 surge el siguiente problema:

        $ ./virtualenv27/bin/python src/dynamicware/manage.py test myprojects
        Creating test database for alias 'default'...
        (...)
        psycopg2.ProgrammingError: autocommit cannot be used inside a transaction



        Una solución temporal es instalar la versión anterior de psycopg2:

        $ ./virtualenv27/bin/pip install psycopg2==2.4.1

        La solución definitiva ya existe: https://code.djangoproject.com/ticket/16250

        PIL / pillow + virtualenv

        Instalé PIL usando virtualenv, y así termina la instalción:


            --------------------------------------------------------------------
            PIL 1.1.7 SETUP SUMMARY
            --------------------------------------------------------------------
            version       1.1.7
            platform      linux2 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
                          [GCC 4.5.2]
            --------------------------------------------------------------------
            *** TKINTER support not available (Tcl/Tk 8.5 libraries needed)
            *** JPEG support not available
            *** ZLIB (PNG/ZIP) support not available
            *** FREETYPE2 support not available
            --- LITTLECMS support available
            --------------------------------------------------------------------



        PIL se instaló correctamente, pero sin soporte para JPEG y PNG. Este es el funcionamiento "esperado" al instalar PIL con virtualenv.

        La solución: usar pillow (fork PIL, amigable con virtualenv)

        Luego de ejecutar "./virtualenv27/bin/pip install pillow":


            --------------------------------------------------------------------
            Pillow 1.7.4 ( PIL fork based on PIL 1.1.7 ) SETUP SUMMARY
            --------------------------------------------------------------------
            platform  linux2 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
              [GCC 4.5.2]
            --------------------------------------------------------------------
            *** TKINTER support not available (Tcl/Tk 8.5 libraries needed)
            --- JPEG support available
            --- ZLIB (PNG/ZIP) support available
            --- FREETYPE2 support available
            --- LITTLECMS support available
            --------------------------------------------------------------------

        domingo, 17 de julio de 2011

        Storage distribuido con SheepDog

        Instalé SheepDog siguiendo las instrucciones del sitio sobre un Debian Sid, todo funcionó excelente!

        Todo el esquema de pruebas lo armé en mi notebook:
        • Host: acer (Ubuntu Desktop 11.04)
          • Guest: debian-virt-server-01 (Debian Sid / libvirt+KVM)
            • ejecutando SheepDog
          • Guest: debian-virt-server-02 (Debian Sid / libvirt+KVM)
            • ejecutando SheepDog
          • Guest: debian-virt-server-03 (Debian Sid / libvirt+KVM)
            • ejecutando SheepDog
          • Guest: linux-over-sheepdog (Ubuntu 10.04 Server / QEMU)
            • usando "linux-over-sheepdog" como disco (esta imagen es creada usando qemu-img).
        Luego configuré coresync y arranqué sheepdog en debian-virt-server-01debian-virt-server-02 y debian-virt-server-03.

        Ahora, a crear la imagen de disco!

        root@debian-virt-server-01:~# collie cluster format --copies=2

        Este comando sólo se debe ejecutar en 1 nodo.

        root@debian-virt-server-01:~# collie node list
         Idx - Host:Port Number of vnodes
        ------------------------------------------------
        * 0 - 192.168.122.101:7000 64
         1 - 192.168.122.102:7000 64
         2 - 192.168.122.103:7000 64
        El cluster fue "formateado" para que mantenga 2 copias de la información. Los 3 nodos se están viendo, ya que aparecen al ejecutar "collie node list". 

        Creamos imagen para ser usado como disco

        acer| ~$ qemu-img create sheepdog:192.168.122.101:7000:linux-over-sheepdog 4G
        Formatting 'sheepdog:192.168.122.101:7000:linux-over-sheepdog', fmt=raw size=4294967296
        Booteamos QEMU

        acer| ~$ qemu-system-x86_64 -enable-kvm -m 512 -cdrom ubuntu-10.04-server-amd64-LTS.iso sheepdog:192.168.122.101:7000:linux-over-sheepdog

        Y listo! La instalación de Ubuntu Server se inició correctamente sobre un "disco virtual" hosteado usando SheepDog.



        miércoles, 13 de julio de 2011

        Procesamiento de anotaciones en Java

        Hay un bug en la JVM de Sun Oracle que hace fallar el procesamiento de anotaciones. Me pasó que compilando el proyecto funcionaba OK, pero al agregar "-processor ....", aparecía el siguiente problema:


        [javac] /...../ValidationCheck.java:25: incompatible types
        [javac] found   : ......annotations.Type
        [javac] required: ......Type
        [javac] Type type() default Type.WORKER;

        El problema es el Enum "Type". Este Enum existe y está en el classpath, pero javac "no la ve". Está definido de la siguiente manera:

        Type type() default Type.WORKER;

        La solución para zafar de este bug es introducir el paquete en el nombre del Enum, de manera que quede:

        Type type() default my.package.annotations.Type.WORKER;


        Y con eso compila!

        BUGhttp://bugs.sun.com/view_bug.do?bug_id=6512707

        viernes, 1 de julio de 2011

        Cómo usar dispositivos USB desde KVM

        Quiero usar mi pendrive desde un guest KVM (gestionado por libvirt). El dispositivo USB es el marcado con negrita:

        acer| ~$ lsusb
        Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
        Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
        Bus 002 Device 004: ID 0930:6545 Toshiba Corp. Kingston DataTraveler 102 flash drive

        Primera opción: usando vendor id + product id

        Editamos el XML usando "virsh edit", y agregamos lo siguiente en el elemento devices:



        Esta opción asocia un "tipo de dispositivo" (en este caso, el pendrive Kingston) al guest KVM, sin importar en qué puerto se conecte.

        Segunda opcióni: usando bus + device

        Editamos el XML usando "virsh edit", y agregamos lo siguiente en el elemento devices:



        Esta opción asocia un puerto USB al guest, sin importar qué tipo de dispositivo se conecte.

        sábado, 18 de junio de 2011

        AppEngine: cómo evitar subir contenidos de un directorio

        Al trabajar con Google App Engine, podemos crear un directorio en la base del proyecto, y luego configurar app.yaml para que ignore estos archivos. Por ejemlpo, si el directorio se llama local, hay que agregar a las siguientes líneas al archivo app.yaml:

        skip_files:
        - ^(.*/)?app\.yaml
        - ^(.*/)?app\.yml
        - ^(.*/)?index\.yaml
        - ^(.*/)?index\.yml
        - ^(.*/)?#.*#
        - ^(.*/)?.*~
        - ^(.*/)?.*\.py[co]
        - ^(.*/)?.*/RCS/.*
        - ^(.*/)?\..*
        - ^local/.*
        

        Todas las líneas excepto la última, corresponden a la configuración por default de skip_files. La última línea hace que el directorio local en la raiz del proyecto sea ignorado al ejecutar appcfg.py.

        miércoles, 15 de junio de 2011

        Compactar particiones con zerofree

        Para realizar backups de imágenes de discos usadas en QEmu/KVM se puede optimizar usar zerofree. Este programa  escribe 0 (ceros) en los lugares de la imagen que NO está siendo usada por archivos, y que han sido usadas pero actualmente están libres (por ejemplo, en el lugar donde se haya creado un archivo que luego haya sido borrado).

        Zerofree funciona para ext2/ext3/ext4, en particiones que no están montadas, o montadas solo-lectura. Esta utilidad es "inteligente" en el sentido que no hace "crecer" a los archivos sparse. 


        Los pasos a seguir son:

        • cargar nbd

           ~$ sudo modprobe nbd max_part=16

        • asociar imagen de disco disk01.qcow2nbd1 y crear dispositivos asociados a particiones

           ~$ sudo qemu-nbd -c /dev/nbd1 -v disk01.qcow2
           ~$ sudo partprobe /dev/nbd1

        • ejecutar zerofree

           ~$ sudo zerofree -v /dev/nbd1p5

        Listo! El archivo "disk01.qcow2" ocupa teóricamente 11G, pero como es un archivo sparse, en realidad está ocupado en disco sólo 1.9G:


           ~$ ls -lh disk01.qcow2
           -rw-r--r-- 1 root root 11G 2011-06-15 14:51 disk01.qcow2
           ~$ du -h disk01.qcow2 

           1.9G disk01.qcow2

        El .tar ocupa sólo 918M:

           ~$ tar --sparse -cf disk01.qcow2.tar disk01.qcow2
           ~$ ls -lh disk01.qcow2.tar 
           -rw-r--r-- 1 horacio horacio 918M 2011-06-15 15:10 disk01.qcow2.tar

        Y al comprimirlo solo nos queda 305M:

           $ gzip -1 disk01.qcow2.tar 
           $ ls -lh disk01.qcow2.tar.gz 
           -rw-r--r-- 1 horacio horacio 305M 2011-06-15 15:10 disk01.qcow2.tar.gz



           ~$ du -h *
           1.9G disk01.qcow2
           305M disk01.qcow2.tar.gz



        En este caso, un archivo que ocupa inicialmente 1.9G lo llevamos a ocupar 918M (305M comprimido).

        jueves, 9 de junio de 2011

        Cómo compilar cliente spice

        Seguiendo los pasos para instalar Spice (un nuevo protocolo para comunicarse con guests KVM/QEMU/etc.) me surgieron unos errores, no muy complicados de resolver.

        En general, segui las instrucciones de http://spice-space.org/page/Building_Instructions.
        La instalación la hice en /usr/local/slice, asi que reemplace "INST_ROOT" por "/usr/local/slice".


        Para compilar e instalar el cliente, en un momento hay que ejecutar:

        ~$ cd $SRC_ROOT/spice
        ~$ ./autogen.sh --prefix=$INST_ROOT

        Pero este ultimo comando me generó un error:


        ----------------------------------------
        (...)
        checking for PROTOCOL... no
        configure: error: Package requirements (spice-protocol >= 0.6.0) were not met:
        No package 'spice-protocol' found
        Consider adjusting the PKG_CONFIG_PATH environment variable if you
        installed software in a non-standard prefix.
        Alternatively, you may set the environment variables PROTOCOL_CFLAGS
        and PROTOCOL_LIBS to avoid the need to call pkg-config.
        See the pkg-config man page for more details.
        ----------------------------------------

        Esto se solucione usando:

        ~$ export PKG_CONFIG_PATH="/usr/local/spice/share/pkgconfig:/usr/local/spice/lib/pkgconfig"
        ~$ ./autogen.sh --prefix=/usr/local/spice
        ~$ cd client
        ~$ make install

        Y... no funcionó...

        ----------------------------------------
        make[1]: *** No rule to make target `../common/libspice-common.la', needed by `spicec'. Stop.
        make[1]: Leaving directory `/mnt/sin_encriptar/src/spice-client-src/spice/client'
        make: *** [install] Error 2

        ----------------------------------------

        Pero, compilando manualmente lo del directorio "common", luego lo de "cliente" funciona:

        ~$ cd ..
        ~$ cd common
        ~$ make install
        ~$ cd ..
        ~$ cd client
        ~$ make install

        Y ahora sí!

        viernes, 3 de junio de 2011

        Eliminando *.pyc del repositorio Git

        Por un error subí archivos pyc al repositorio Git. Ya que no me hace falta mantener esos archivos en el repositorio, decidí intentar eliminarlos del historial, usando "git filter-branch". Resultó ser bastante fácil!

        $ git filter-branch --tag-name-filter cat \
        --index-filter 'git rm -r --cached --ignore-unmatch *.pyc' HEAD

        Esto no es peligroso para repositorios "personales", pero SI para repositorios compartidos, ya que este comando reescribe todo el historial. También hay que tener cuidado si se están utilizando varios branches, ya que este comando solo trabaja en 1 branch a la vez.

        La documentación del comando puede verse aqui.

        Probando LM335 con PyArduinoProxy

        Subi unos screenshots, mostrando cómo usé la interfaz web de PyArduinoProxy para testear unos LM335.

        https://github.com/hgdeoro/py-arduino-proxy/wiki/Example%3A-Testing-LM335

        miércoles, 25 de mayo de 2011

        Chau Skype!

        La compañía Skype fue comprada, asi que ya es hora de buscar alternativas!

        sábado, 14 de mayo de 2011

        Flyback diode

        Son diodos utilizados para eliminar repentinos picos de voltaje. Estos picos se producen en circuitos altamente inductivos, cuando el voltaje en dicho circuito baja o es eliminado.


        La teoría de circuitos demuestra que cuando la corriente que pasa por un inductor se detiene, aparece una tensión a tavés de dicho inductor, en sentido contrario de la corriente que se detuvo. Esta corriente es llamada "flayback". Esa corriente no "aparece de la nada": es originada en la energía almacenada en el campo magnético del inductor, o sea, el campo magnético creado por la corriente inicial, libera su energía como electricidad (pero en sentido opuesto a la corriente inicial).

        Tomada de WikiPedia: http://en.wikipedia.org/wiki/File:Flyback_Diode.svg





        Hay más información (en inglés) en: http://en.wikipedia.org/wiki/Flyback_diode

        Capacitores para suprimir ruido eléctrico

        Encontré que es aconsejable utilizar capacitores en los circuitos, para suprimir cualquier "ruido" que pueda generarse, sobre todo si se usan motores (me imagino que también debe ser importante si se usan reles, por ejemplo).

        http://www.seattlerobotics.org/encoder/jun97/basics.html
        En inglés: Bypass capacitors help filter the electrical noise out of your circuits. They do this by removing the alternating currents caused by ripple voltage. Most digital circuits have at least a couple of bypass capacitors. A good rule of thumb is to add one bypass capacitor for every integrated circuit on your board. A good default value for a bypass cap is 0.1uF. Higher frequencies require lower valued capacitors.

        Traducido por Google: Los condensadores de desacoplo ayudan a filtrar el ruido eléctrico de los circuitos. Lo hacen mediante la eliminación de las corrientes alternas causada por variaciones de la tensión. La mayoría de los circuitos digitales tienen por lo menos un par de condensadores de desacoplo. Una buena regla es agregar un condensador de desacoplo por cada circuito integrado en la placa. Un buen valor por defecto es 0.1uF. Las frecuencias más altas requieren capacitores de menor valor .
         Otras páginas interesantes que encontré sobre el tema:

        viernes, 6 de mayo de 2011

        Py-Arduino-Proxy + LCD

        Ya estoy buscando la forma de utilizar LCDs desde Py-Arduino-Proxy :-D En este caso, muestro la temperatura (con un LM35)


        sábado, 30 de abril de 2011

        Como tomar screenshots automáticamente y convertirlos en video

        Primer paso: crear la secuencia de screenshots, usando la utilidad "scrot":

        • s=1; while /bin/true ; do scrot -q 80 "${s}.png" -e "convert -crop 800x600+0+24 ${s}.png ${s}.jpg" ; let s=s+1 ; sleep 1 ; done
        Atención! Este comando sobrescribirá cualquier archivo preexistente! Para continuar una secuencia pre-existente, se puede cambiar el valor inicial de "s". Por ejemplo, si ya tenemos desde el archivo 1.png hasta el 71.png, podemos usar s=72:
        • s=72; while /bin/true ; do scrot -q 80 "${s}.png" -e "convert -crop 800x600+0+24 ${s}.png ${s}.jpg" ; let s=s+1 ; sleep 1 ; done
        Segundo paso: generar un video con dicha secuencia de archivos, usando "ffmpeg":
        • ffmpeg -r 4 -b 512k -i %d.jpg OUTPUT.avi
        Actualización: para que ffmpeg funcione, los nombres de los archivos deben ser secuenciales, y sin ningún archivo faltante. Por lo tanto, si antes de generar el video queremos borrar algunos archivos, vamos a tener problemas. Pero hay una forma muy fácil de crear una secuencia de archivos, arreglando los 'faltantes':
        • max=1000 ; ren=1 ;  for f in `seq 1 $max` ; do [ -e $f.jpg ] && { [ $f -ne $ren ] && { echo mv -i $f.jpg $ren.jpg ; } ; let ren=ren+1 ; } ; done
        Ese pequeño script generará por pantalla todos los 'mv' que hace falta ejecutar para arreglar la secuencia. Si quitamos el 'echo', el script ejecutará directamente el comando 'mv'. Ajustar 'max' al número más grande dentro de la secuencia.

        martes, 26 de abril de 2011

        os.path.normpath() de Python y las //

        No es la primera vez que me sucede! Otra vez caí en el extraño funcionamiento  de os.path.normpath()!

        os.path.normpath('/esto') = '/esto'
        os.path.normpath('/esto/') = '/esto'
        os.path.normpath('//esto') = '//esto'
        os.path.normpath('//esto/') = '//esto'
        os.path.normpath('///esto') = '/esto'
        os.path.normpath('///esto/') = '/esto'

        Quizá las 2 barras se mantienen al suponer que es un path referenciando algún recurso como se hace en las redes Windows, al estilo //equipo/recurso_compartido.

        Solución: usar strip('/') y concatenar un '/' al inicio (suponiendo que siempre trabajamos con path absolutos).


        '/' + os.path.normpath('/esto').strip('/') = '/esto'
        '/' + os.path.normpath('/esto/').strip('/') = '/esto'
        '/' + os.path.normpath('//esto').strip('/') = '/esto'
        '/' + os.path.normpath('//esto/').strip('/') = '/esto'
        '/' + os.path.normpath('///esto').strip('/') = '/esto'
        '/' + os.path.normpath('///esto/').strip('/') = '/esto'


        lunes, 25 de abril de 2011

        Para acceder Arduino desde Python y scripts shell

        He creado una aplicación para acceder a Arduino desde Python. También incluyo unos ejempos para poder accederlos desde el shell. El proyecto está en https://github.com/hgdeoro/py-arduino-proxy

        Utilizando un LM35 para medir la temperatura. Necesita 3 cables, 5V, masa, y la "señal".



        En el Arduino, conecto los respectivos cables, y el de señal al puerto analógico 0.



        El sensor lo dejo afuera, a pleno rayo de sol, y por ahora bajo la protección de un simple fondo de botella.




        Agregar plugin de Munin

        Sólo hacer un link del script al directorio de plugins:

        root@eeepc:~# cd /etc/munin/plugins/
        root@eeepc:/etc/munin/plugins# ln -s \
        /usr/local/py-arduino-proxy/src/arduino_proxy/tests/analog_read_lm35_munin.py \
        analog_read_lm35_munin_
        root@eeepc:/etc/munin/plugins# mcedit ../plugin-conf.d/munin-node
        ## AGREGAR ESTO AL FINAL DEL ARCHIVO
        [analog_read_lm35_munin]
        user root
        env.TTY_DEVICE /dev/ttyACM0
        env.ANALOG_PORT 0
        

        Y ahora sólo resta reiniciar munin-node.

        root@eeepc:/etc/munin/plugins# service munin-node restart
        munin-node start/running, process 22555
        root@eeepc:/etc/munin/plugins# 
        

        Y testear que todo haya quedado funcionando correctamente:

        root@eeepc:/etc/munin/plugins# munin-run analog_read_lm35_munin
        temp.value 10.11

        Luego de dos días:







        El circuito al que se conecta el LM35 sería así:

        viernes, 15 de abril de 2011

        Para zafar del problema con Arduino + Ubuntu

        He armado un sketch para "zafar" de los problemas que hay con los Arduinos cuando queremos accederlos desde Ubuntu. Sucede que por un bug, tendremos problemas al intententar subir sketchs desde Ubuntu, si en ese momento el Arduino envía información por puerto serial (por ejemlpo usando usando Serial.println()).

        La solución definitiva es actualizar el firmware. Otra (la que implementé) es "pausar" la ejecución del programa, hasta que se detecta un "LOW" en el pin 12.

        El programa es:





        Y la forma de generar le "LOW" en el pin 12 sería:

        Lo que hago es dejar la resistencia conectada, así el Arduino funciona con normalidad. Cuando necesito subir un programa nuevo, le saco la resistencia y lo reinicio, y puedo comunicarme sin problemas.

        sábado, 19 de marzo de 2011

        (Injusta) comparación de OpenStack Object Storage y MongoDB

        Aclaración: antes que nada, quiero aclarar que no es justo para MongoDB compararlo con Object Storage. Mi intención es sólo comentar mi experiencia.


        Ante la necesidad de guardar una gran cantidad de archivos en una aplicación web (más de 80GB), realicé pruebas con MongoDB (versiones 1.6.5 y 1.7.3), ya que entre las bases de datos NoSql, es la única que encontré que provee el API necesario para guardar y obtener  archivos almacenados (GridFS) (además permite ser configurado muy fácilmente para que los datos almacenados se repliquen entre distintas instancias de MongoDB). Pero me encontré con 2 problemas:
        1. Poca eficiencia en la utilización del espacio en disco: en las pruebas realizadas, al insertar archivos por un total de 12GB, en disco se utilizó 21GB.
        2. Dificultad para recuperar el espacio ocupado de archivos borrados: el borrado de los archivos es un "borrado lógico", y para recuperar el espacio que utilizan, hace falta ejecutar "repairdb()", que básicamente, hace una copia de la BD, de todos los datos no-borrados... esto es un problema si la base de datos es más grande que el espacio libre de la partición.
        Este tipo de problemas los pude superar usando OpenStack Object Storage (versión 1.2.0):
        1. Utilización de espacio en disco: al insertar archivos por 4202MB, en disco se utilizó 4281MB.
        2. Recuperación de espacio en disco: el espacio es liberado al borrar los archivos.
        En cuanto a las pruebas de stress:
        • MongoDB en ningún caso dió error
        • al realizar pruebas con Object Storage, he obtenido algunos "Read timed out" al momento de subir los archivos.
        Cabe aclarar que MongoDB lo corria directamente en mi computadora, en cambio, Object Storage estaba instalado en una guest KVM.

        En cuanto a la instalación:
        • la instalación de MongoDB me llevó muy poco tiempo y es muy fácil
        • la de Object Storage me costó más, sobre todo la utilización desde Java, ya que el cliente de Java necesita validar correctamente los certificados SSL con los que se configuró el servidor (algo que no pasa con el cliente Python).

        jueves, 17 de marzo de 2011

        Funciones privadas para unittest.assertRaises()

        Para facilitar el uso de unittest.assertRaises() podemos usar funciones privadas. Esto al menos con python < 2.7 (ya que en python 2.7 assertRaises() permite ser usado como "context manager").


        sábado, 12 de marzo de 2011

        OpenStack Object Storage - Ejemplo con Python

        Adjunto un pequeño ejemplo en Python.


        ----- Inicio del ejemplo -----

        ----- Fin del ejemplo -----

        viernes, 11 de marzo de 2011

        Probando OpenStack Object Storage

        Luego de unas horas, pude tener andando mi instancia de OpenStack Object Storage. El servidor lo instalé en un Ubuntu 10.04.2 LTS (Lucid), siguiendo las instrucciones de Installing OpenStack Object Storage on Ubuntu.

        Algunas cuestiones a tener en cuenta:

        • En la página de "Configuring OpenStack Object Storage", al crear los "self-signed certs" utilizando el comando "openssl req -new -x509 -nodes -out cert.crt -keyout cert.key", en un momento solicita "Common Name (eg, YOUR name) []:"; aquí hay que ingresar el nombre del host que se utilizará para conectarse, o el IP con el que se accederá al Object Storage desde la red. Por ejemplo, en mi caso, utilicé "192.168.122.233". Al conectarnos desde Python, no parece influir el "Comon Name" elegido, pero sí influye al conectarnos desde Java.
        • En vez de usar "swift-ring-builder account.builder create 18 3 1", utilicé "swift-ring-builder account.builder create 18 1 1", ya que sólo hay 1 servidor. Quizá se pueda usar 3, y de esa manera, al agregar servidores, los datos se distribuyan automáticamente...
        • Al ejecutar los comandos "swift-ring-builder account.builder add ...." hay que especificar "DEVICE"... Bueno, aunque el parámetro se llama "device", esto NO se refiere a la partición! Sino al nombre del directorio donde está montada la partición donde se guardarán los datos. El servicio supone que las particiones donde se guardarán los datos están montadas en "/srv/node/DEVICE". Por ejemplo, si los datos los vamos a guardar en la partición /dev/sdb1, y montamos esa partición en "/srv/node/sdb1", entonces DEVICE = sdb1. NO hay que tomar a DEVICE como /dev/sdb1, esto es un error. Por ejemplo, en mi caso, utilice "sdb1" como DEVICE (para seguir la nomenclatura de la documentación), pero en realidad utilizo la partición "/dev/vdb1", ya que es un instancia de KVM y utilizo virtio para mapear los discos. Por lo tanto, en el fstab tengo: "/dev/vdb1 /srv/node/sdb1 xfs noatime,nodiratime,nobarrier,logbufs=8 0 0".
        Los fuentes del servidor (Swift) pueden bajarse de http://www.openstack.org/projects/storage/. El cliente para Python, puede bajarse de https://github.com/rackspace/python-cloudfiles. El de Java, desde https://github.com/rackspace/java-cloudfiles. Desarrollar un pequeño test en Python fue sencillo. En Java fue bastante más complicado, porque  al utilizar certificados firmados por mí mismo (al instalar el servidor genere los certificados con openssl, y por lo tanto no fueron firmados por una entidad de confianza), y por lo tanto Java generaba errores al intentar crear la conexión https a un servidor con certificados no confiables... Más información de esto en un próximo post :-)