Archivo

Archivo para la categoría ‘linux’

Cómo compartir un dispositivo serie por la red en Linux

lunes, 27 de mayo de 2013 Sin comentarios

En el trabajo me encontré con la necesidad de utilizar un puerto serial (por ejemplo, un dispositivo con un adaptador USB/Serie en /dev/ttyUSB0, un módem 3G o una placa Arduino en /dev/ttyACM0, etc.) conectado físicamente a una máquina en mi red, que por diferentes motivos (distancia, pereza, lo que sea), lo quería acceder con un programa en mi máquina, pero como si fuera local.

Es decir, tenía un programa en mi máquina que usa pySerial para acceder al Arduino en /dev/ttyACM0, pero por diferentes motivos el Arduino está conectado en otra máquina de mi red y quería que, sin tocar mi programa, éste acceda al Arduino como si estuviera directamente conectado a mi PC, haciendo de alguna manera «transparente» la red que nos separaba. Por suerte lo pude resolver, y quizás esta herramienta y acercamiento sirva a más de uno para resolver algún otro problema similar.

Para esto vamos a utilizar la herramienta socat, que es como netcat pero para streams bidireccionales. Los pasos son:

  • Instalar socat (apt-get install socat), tanto en la máquina que tiene el dispositivo serie real (vamos a llamarlo «servidor») como en el «cliente».
  • Ejecutar en el servidor: «socat -d -d -d OPEN:/dev/ttyACM0 TCP4-LISTEN:31337»:
usuario@servidor:~$ socat -d -d -d OPEN:/dev/ttyACM0 TCP4-LISTEN:31337
2013/05/27 10:40:53 socat[2703] I socat by Gerhard Rieger - see www.dest-unreach.org
2013/05/27 10:40:53 socat[2703] I This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)
2013/05/27 10:40:53 socat[2703] I This product includes software written by Tim Hudson (tjh@cryptsoft.com)
2013/05/27 10:40:53 socat[2703] N opening character device "/dev/ttyACM0" for reading and writing
2013/05/27 10:40:53 socat[2703] I open("/dev/ttyACM0", 02, 0666) -> 3
2013/05/27 10:40:53 socat[2703] I socket(2, 1, 6) -> 4
2013/05/27 10:40:53 socat[2703] I starting accept loop
2013/05/27 10:40:53 socat[2703] N listening on AF=2 0.0.0.0:31337
2013/05/27 10:40:58 socat[2703] I accept(4, {2, AF=2 192.168.1.150:44624}, 16) -> 5
2013/05/27 10:40:58 socat[2703] N accepting connection from AF=2 192.168.1.150:44624 on AF=2 192.168.1.93:31337
2013/05/27 10:40:58 socat[2703] I permitting connection from AF=2 192.168.1.150:44624
2013/05/27 10:40:58 socat[2703] I close(4)
2013/05/27 10:40:58 socat[2703] I resolved and opened all sock addresses
2013/05/27 10:40:58 socat[2703] N starting data transfer loop with FDs [3,3] and [5,5]

Esto hace que socat abra el archivo /dev/ttyACM0 (el dispositivo serie a compartir), y además abra un socket en modo LISTEN (escuchando por conexiones) en todas las interfaces del equipo, particularmente en el puerto 31337. Las opciones -d -d -d son opcionales y sirve para habilitar los mensajes de debug.

  • Ejecutar en el cliente «socat -d -d -d TCP4:192.168.1.93:31337 PTY,link=/dev/ttyACM0»:
usuario@cliente:~$ socat -d -d -d TCP4:192.168.1.93:31337 PTY,link=/tmp/ttyACM0
2013/05/27 11:52:34 socat[8408] I socat by Gerhard Rieger - see www.dest-unreach.org
2013/05/27 11:52:34 socat[8408] I This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)
2013/05/27 11:52:34 socat[8408] I This product includes software written by Tim Hudson (tjh@cryptsoft.com)
2013/05/27 11:52:34 socat[8408] N opening connection to AF=2 192.168.1.93:31337
2013/05/27 11:52:34 socat[8408] I starting connect loop
2013/05/27 11:52:34 socat[8408] I socket(2, 1, 6) -> 3
2013/05/27 11:52:34 socat[8408] N successfully connected from local address AF=2 192.168.1.150:45293
2013/05/27 11:52:34 socat[8408] I setting option "symbolic-link" to "/tmp/ttyACM0"
2013/05/27 11:52:34 socat[8408] I openpty({4}, {5}, {"/dev/pts/4"},,) -> 0
2013/05/27 11:52:34 socat[8408] N PTY is /dev/pts/4
2013/05/27 11:52:34 socat[8408] I resolved and opened all sock addresses
2013/05/27 11:52:34 socat[8408] N starting data transfer loop with FDs [3,3] and [4,4]

Este comando hace que el socat de mi máquina se conecte a la IP 192.168.1.93 (allí debe estar el servidor), al puerto 31337, y que localmente lo haga ver como un nuevo dispositivo serial (pseudo terminal) creado por socat mismo en /dev/pts/X, y además haga un symlink de éste al archivo /tmp/ttyACM0. A partir de éste momento en /tmp/ttyACM0 existe un archivo que puede ser abierto con pyserial (por ejemplo, puede ser minicom, etc.) y ser utilizado como un dispositivo serie local.

Un detalle, cuando se cierra la conexión del socat en el cliente hacia el servidor, en el servidor también se termina la ejecución del socat (y viceversa), por lo que en caso de volver a establecer la sesión, es necesario ejecutar nuevamente en ambos equipos.

Saludos

Categories: codear, linux, programación, sysadmin Tags:

Instalando DD-WRT en un TP-Link TL-WR941ND

sábado, 2 de junio de 2012 169 comentarios

Uno compra un Router/Access Point estos días con la esperanza de que el firmware (software en el equipo) que tiene cargado sea eficiente, no tenga bugs (o al menos tenga actualizaciones periódicas del fabricante que los corrija), e incorpore muchas capacidades interesantes para sacarle el jugo, como el uso de conexiones VPN, priorización de tráfico, poder regular el poder de la antena, gráficos/estadísticas de uso de la conexión, y muchas «cositas» que a nosotros (la gente técnica) nos gusta aprovechar del dispositivo, todo por el mismo precio.

Pero lo más común es que suceda todo lo contrario. Mi router TP-Link TL-WR941ND, apenas lo compré, le actualicé el firmware oficial, y de ahí en más, a los dos o tres días de estar prendido, mágicamente «se cae», dejando de responder, acudiendo obligatoriamente a apagar y encenderlo nuevamente. Ni hablar de actualizaciones posteriores, ni funcionalidades «copadas». Casi que me sentí estafado; siendo previo poseedor de un mítico Linksys WRT54G, lo cambié por el TP-Link que es de norma 802.11N, por ende prometía más velocidad y alcance en mi red.

Pasaron unos meses, hasta que en el FLISOL Luján de este año, Efraim me instaló en el Linksys un firmware libre, basado en Linux, llamado DD-WRT que funciona en muchísimos modelos de Access Points/Routers (más de 200 según la página, aunque seguro son más). De antemano sabía de la existencia de estos proyectos/distros de Linux, aunque ignoraba lo bien logrado que estaba y las muchísimas capacidades que le agregaba automáticamente al tenerlo instalado.

Es por todo eso que tenía pendiente instalar DD-WRT en mi TP-Link para liberarlo… hasta hoy: migración exitosa.

Puedo comentar que:

  • El proceso de instalación tiene bastantes particularidades, dependiendo mucho del dispositivo y de la versión del hardware que se tiene; sí, dentro de un mismo dispositivo, hay como diferentes «releases» o versiones del hardware (1.0, 2.0, 3.0…), donde el fabricante agrega/saca características, y puede influir tranquilamente en la versión del firmware a instalar.
  • Por lo anterior, sugiero encarecidamente leer toda la documentación, foros y wiki disponible, además de tomar todas las precauciones del caso, ya que un error se puede pagar tirando el router al tacho de basura.
  • Yendo más a mi situación particular, el router TL-WR941ND figura en el Router Database del proyecto, y dice que funciona con la versión 15778 del firmware dd-wrt (que entre otras cosas, ¡parece ser del 2010!). Además está dentro de la página de dispositivos con hardware Atheros soportado.
  • Yo tengo la versión 3.6 del hardware, lo compré hace algunos meses nomás en Galería Jardín, así que es bastante probable que todavía y por un tiempo haya versiones iguales dando vueltas.
  • Lo único que hice fue buscar, en foros, como documentación, y encontré que el «router database» estaba desactualizado, y había una versión mucho más actualizada y probada que no estaba linkeada en la página (está en este FTP).
  • La parte más fácil fue el upgrade en sí: sólo tuve que ir a «Upload firmware» en el administrador web del TP-Link, subí el archivo «factory-to-ddwrt.bin» que bajé del FTP, apagar/prender y listo. 🙂

Ahora tengo muchísimas más opciones y potencia que antes en mi equipo y la casi certeza de que va a funcionar correctamente. En este mismo FTP también se van subiendo periódicamente las versiones nuevas del dd-wrt (del 2012), separada por equipo/versión de hardware: ftp://dd-wrt.com/others/eko/BrainSlayer-V24-preSP2/2012/

A disfrutar del Software Libre se ha dicho. 🙂

¡Saludos!

Categories: codear, linux, sysadmin Tags:

Virtualizando sólo una partición de una máquina física

viernes, 14 de enero de 2011 10 comentarios

Hace poquito un amigo me contó que estuvo leyendo el post anterior de Consolidación y «Shrinking» de discos físicos para pasarlos a una máquina virtual, pero tenía un pequeño obstáculo relacionado con el espacio en disco necesario, que más o menos era así:

Quería consolidar un disco real de 80 GB que tiene XP instalado en su C:, pero en total el disco tiene 4 particiones (primarias). Sólo me interesaba el disco C:, con lo que ahorraba espacio en el proceso ya que la partición del C: sólo ocupa 25 GB.

Entonces hice la copia con «dd if=/dev/sdb1 of=imagen.raw». Como uso VirtualBox, con un comando lo convertí de .raw a .vdi. Pero no logré bootear.

Hice varias pruebas, siempre con VirtualBox y no lo logré. Supongo que es porque no se copió el MBR. En cambio, cuando copié el disco completo, booteó sin problemas.

La pregunta es: ¿Cómo debería haber hecho para trabajar solo con esa partición y de esa forma evitar trabajar con los 80GB?

Bueno, el problema era que, efectivamente, al hacer el dd sobre /dev/sdb1 sólo se copian los bytes dentro de la partición y no el MBR+Bootloader (la vieja «pista 0» del disco). Para resolver el problema habría que copiar los bytes de la pista 0 más los bytes de la partición en cuestión, siguiendo estos pasos:

Ejecutar el comando parted sobre /dev/sdb (en mi caso, voy a usar /dev/sda como ejemplo):

marcelo@jupiter:~$ sudo parted /dev/sda u s print
Modelo: ATA WDC WD3200BEVT-0 (scsi)
Disco /dev/sda: 625142448s
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. msdos
 
Numero  Inicio     Fin         Tamaño      Tipo      Sistema de ficheros  Banderas
 1      63s        32001479s   32001417s   primary   ext4                 arranque
 2      32001541s  94494329s   62492789s   extended
 5      32001543s  94494329s   62492787s   logical   ext4
 3      94494330s  98494514s   4000185s    primary   linux-swap(v1)
 4      98494515s  625137344s  526642830s  primary   ext4

El parámetro «print» le dice a parted que me imprima la tabla de particiones, y «u s» que imprima los tamaños en sectores (que en los discos <=1.0TB son siempre de 512 bytes, sino mismo parted lo dice en la salida, ver este post para más detalles).

De esta manera se tienen todos los sectores a copiar de /dev/sda directamente; en mi caso, 63 sectores de la pista 0, que contiene al MBR, más los de la primera partición, 32001417, total: 32001480 sectores.

Luego el dd que sólo copia los bytes que nos interesan (Pista 0 + Partición «C:») es fácil:

sudo dd if=/dev/sda of=imagen.raw bs=512 count=32001480

Y listo. Eso sí, luego hay que particionar la imagen con Parted, Fdisk, GParted o el software que se quiera utilizar a tal efecto. Es necesario hacerlo porque el MBR copiado va a reportar las 4 particiones que se tenían previamente en el disco y ahora sólo se va a disponer de una sola.

Asumo que este procedimiento también se puede aplicar para copiar una partición que no sea la primera, usando las opciones «skip» y «append» del comando dd; por ejemplo, si quisiera hacer un disco de sólo mi partición 5, tendría que:

  1. Copiar la pista 0 en un archivo con algo así como «dd if=/dev/sda of=imagen.raw bs=512 count=63».
  2. Ejecutar otro dd con la partición a copiar, salteando («skipeando») N sectores con la opción «skip» y especificando la opción «append» para agregar al archivo anterior de salida: «dd if=/dev/sda of=imagen.raw bs=512 count=62492787 skip=32001543 append».

Lógicamente esto último no lo probé, acepto comentarios de si funcionó o no 😉

Espero que a alguien le sirva…

¡Saludos!

Categories: codear, linux, sysadmin, ubuntu-ar Tags:

Comparativas de Virtualización KVM

miércoles, 5 de enero de 2011 1 comentario

Ultimamente por diferentes cuestiones personales estoy bastante desconectado de la lectura de noticias, blogs y demás. Sin embargo, me pareció útil dejar por acá dos comparativas sobre KVM de Phoronix.com, que si bien en algunos lados me encontré que se quejan de la «calidad» de su suite de benchmarks para software libre/abierto, por el otro, ¡hey! ¡al menos se preocupan en hacerlo! 🙂

Linux KVM vs. VirtualBox 4.0 Virtualization Benchmarks
Este es un test de performance entre KVM y Virtualbox. En resumen, y con los parámetros por defecto en cuanto a I/O, VBox gana, pero parece que es debido a que no hace los fsync del guest en el host y termina utilizando su caché; muy probablemente este comportamiento es configurable (¿ver acá?), pero así y todo ¡es bueno saberlo!. De todas maneras, de alguna manera es peligroso para un entorno de servidores ya que hay riesgo de pérdida de datos, pero por ejemplo, para mi notebook (target primario adonde Virtualbox siempre estuvo orientado) está bien.

Por el otro lado, cuando hay que usar la CPU, KVM «le pasa el trapo» a VBox. Hay un test de I/O de red (TCP) que a KVM le dio mal, tan mal, que seguro es debido a que los salames testers no habilitaron VirtIO en los guests KVM.

Multi-Core Scaling In A KVM Virtualized Environment
Este test trata de dilucidar si es mito o no que el Hyperthreading (las VCPUs) de los microprocesadores Intel Xeon basados en Nehalem hacen más lentas o más rápidas las VMs que corren sobre KVM. Esto es algo que pregunté personalmente en el IRC de KVM (#kvm en Freenode, dicho sea de paso), y me sugirieron lo mismo que dió en los tests: hay veces en donde las VMs aprovechan todas las CPUs virtuales (VCPUs) y otras en que no, con lo cual hay que probar en cada caso en particular y dejar la configuración que nos dé mejores resultados.

Interesante de leer y experimentar.

Saludos

Categories: codear, linux, sysadmin, ubuntu-ar Tags:

Navegador simple con wxPython + Webkit/GTK

sábado, 9 de octubre de 2010 5 comentarios

Hace algunos posts (¡casi un año ya!) escribí sobre una manera fácil y rápida de tener un componente «navegador web» en Python sobre Linux/BSD, gracias a PyGTK y WebkitGTK, llamado lógicamente, pyWebkitGTK. En pocas líneas de código uno puede disponer de un navegador potente y completo en un panel de su aplicación basada en PyGTK, ideal para integrar aún más la cada omnipresente Web.

Las vueltas de la vida y las ganas de experimentar y aprender te llevan a probar otros frameworks/librerías, como lo es wxPython; tanto es así que de vez en cuando tengo el placer de dar alguna charla al respecto [1], y una de las debilidades que le usualmente le encontraba es la falta de un componente «browser web» nativo y soportado en todas las plataformas (wxPython sólo incluye IE embebible como ActiveX en Windows).

En búsqueda de alternativas existe wxWebKit, pero al proyecto le faltan terminar algunas cosas para tener lista su versión «1.0», y si bien wxWebConnect funciona, no da soporte para wxPython, sólo wxWidgets desde C++. Eso nos deja con que en Linux/BSD no tenemos componente que nos dé esta posibildad, pero… si wxPython en estas plataformas utiliza GTK por debajo, ¿no podríamos usar pyWebkitGTK como componente para embeberlo en nuestra aplicación Python?

La respuesta por suerte es afirmativa, y en una rápida búsqueda en la Wiki de wxPython encontré un ejemplo de cómo hacerlo. Si bien podría copiar y pegar la receta, me gustaría «aggiornarla» un poquito, al menos traduciendo y explicando un poco más los comentarios.

Primero vamos a mostrar cómo se vería el módulo que incluye un widget HtmlPanel, wxwebkitgtk.py:

#!/usr/bin/env python
# coding:utf-8
 
"""
    wxWebkitGTK - Componente wxPython que embebe un navegador
                   utiliza la biblioteca Webkit GTK desde Python (PyWebkitGTK).
 
    Marcelo Fidel Fernández - http://www.marcelofernandez.info
    Basado en: http://wiki.wxpython.org/wxGTKWebKit
"""
import os
import wx
import gobject
gobject.threads_init()
import gtk, gtk.gdk
import webkit
 
class HtmlPanel(wx.Panel):
 
    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)
        # Aquí es donde se hace la "magia" de embeber webkit en wxGTK.
        whdl = self.GetHandle()
        window = gtk.gdk.window_lookup(whdl)
        # Debemos mantener la referencia a "pizza", sino obtenemos un segfault.
        self.pizza = window.get_user_data()
        # Obtengo el padre de la clase GtkPizza, un gtk.ScrolledWindow
        self.scrolled_window = self.pizza.parent
        # Saco el objeto GtkPizza para poner un WebView en su lugar
        self.scrolled_window.remove(self.pizza)
        self.webview = webkit.WebView()
        self.scrolled_window.add(self.webview)
        self.scrolled_window.show_all()

La «magia» consiste en que, sabiendo que pyWebkitGTK necesita un componente ScrolledWindow GTK como padre para funcionar correctamente, se utiliza la biblioteca PyGTK para buscar el ScrolledWindow GTK donde está embebido el wx.Panel de la clase (su «abuelo»), y reemplazar el hijo GTKPizza (un componente inventado por wxWidgets para funcionar) por el WebView de Webkit.

Aquí hay un ejemplo de cómo se puede utilizar este panel como widget de wxPython completo e independiente, copiando la funcionalidad básica del post de PyWebkitGTK, el archivo wxwebkitgtk_demo.py:

#!/usr/bin/env python
# coding: utf-8
 
"""
    wxSimpleBrowser - Navegador muy muy simple de internet, sólo de ejemplo,
                      que utiliza la biblioteca Webkit GTK desde wxPython.
 
    Marcelo Fidel Fernández - http://www.marcelofernandez.info
    Licencia: BSD. Disponible en: http://www.freebsd.org/copyright/license.html
"""
 
import sys
import wx
from wxwebkitgtk import HtmlPanel
 
DEFAULT_URL = 'http://www.python.org'
 
class wxSimpleBrowser(wx.Frame):
 
    def __init__(self):
        wx.Frame.__init__(self, None)
        self.TxtUrl = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
        self.TxtUrl.Bind(wx.EVT_TEXT_ENTER, self.OnTxtURL)
        self.Box = wx.BoxSizer(wx.VERTICAL)
        self.Box.Add(self.TxtUrl, proportion=0, flag=wx.EXPAND)
        self.SetSizer(self.Box)
        self.SetSize((800,600))
        self.Show()
        # Necesitamos tener mostrado el componente padre del Panel para que funcione,
        # por eso mostramos primero el Frame y después creamos el HtmlPanel
        self.HtmlPanel = HtmlPanel(self)
        self.Box.Add(self.HtmlPanel, proportion=1, flag=wx.EXPAND)
        self.SendSizeEvent() # Para acomodar el panel al tamaño del frame
 
    def OnTxtURL(self, event):
        self.Open(self.TxtUrl.GetValue())
 
    def Open(self, url):
        # Podemos acceder a todos los métods del objeto WebView
        # http://webkitgtk.org/reference/webkitgtk-webkitwebview.html
        self.HtmlPanel.webview.load_uri(url)
        self.TxtUrl.SetValue(url)
        self.SetTitle('wxSimpleBrowser - %s' % url)
 
if __name__ == '__main__':
    if len(sys.argv) &gt; 1:
        url = sys.argv[1]
    else:
        url = DEFAULT_URL
    app = wx.App()
    browser = wxSimpleBrowser()
    browser.Open(url)
    app.MainLoop()

Creo que para la enorme funcionalidad que nos brinda el proceso de ponerlo en práctica es bastante simple, y aunque depende de PyGTK, ésta biblioteca hoy está disponible «de fábrica» en cualquier distribución moderna de GNU/Linux.

De aquí en más es ser muy sencillo dejar al lector el armado de un widget para wxPython que en Windows muestre el componente navegador de IE y en Linux un navegador Webkit.

[1] ¡La semana que viene voy a estar en la PyCon Argentina 2010 dando una charla de Introducción a wxPython! 😀

¡Saludos!

Categories: codear, linux, programación, python, ubuntu-ar Tags: