sábado, 20 de agosto de 2011

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.