<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>El Blog de Marcelo! » ubuntu-ar</title>
	
	<link>http://blog.marcelofernandez.info</link>
	<description>Blog Informático sobre Programación, Software Libre y/o Open Source, Linux, Python y alguna que otra cosa más...</description>
	<lastBuildDate>Sat, 14 Aug 2010 07:14:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ElBlogDeMarcelo_ubuntu-ar" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="elblogdemarcelo_ubuntu-ar" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Achicando imágenes de Máquinas Virtuales (KVM-QCow2)</title>
		<link>http://blog.marcelofernandez.info/2010/08/achicando-imagenes-de-maquinas-virtuales-kvm-qcow2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=achicando-imagenes-de-maquinas-virtuales-kvm-qcow2</link>
		<comments>http://blog.marcelofernandez.info/2010/08/achicando-imagenes-de-maquinas-virtuales-kvm-qcow2/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 07:14:26 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=936</guid>
		<description><![CDATA[Consolidando Máquinas Físicas a Virtuales Dentro del mundo de la Virtualización, al momento de consolidar máquinas [1] lo más sencillo (o lo que primero se le puede ocurrir a uno [2]) es hacer una imagen bit a bit del disco donde éste se aloja a un archivo del Host, mediante alguna herramienta como dd en [...]]]></description>
			<content:encoded><![CDATA[<h2>Consolidando Máquinas Físicas a Virtuales</h2>
<p>Dentro del mundo de la Virtualización, al momento de consolidar máquinas <a href="#1">[1]</a> lo más sencillo (o lo que primero se le puede ocurrir a uno <a href="#2">[2]</a>) es hacer una imagen bit a bit del disco donde éste se aloja a un archivo del <em>Host</em>, mediante alguna herramienta como <a href="http://en.wikipedia.org/wiki/Dd_(Unix)" target="_blank">dd</a> en Linux:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ dd if=/dev/sdb of=/vms/images/imagen.raw</pre></div></div>

<p>Este mecanismo es generalmente infalible; luego de ésto, uno crea un perfil de una Máquina Virtual (típicamente un archivo XML donde se describen las características del <em>Guest</em>), se lo relaciona a esta imagen &#8220;cruda&#8221; de la ex-Máquina Física, y en un minutos la misma está corriendo como Máquina Virtual sin problemas.</p>
<p>Además, es más común utilizar un formato de imágenes más flexible que el Raw (&#8220;crudo&#8221;), que soporte características como:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Virtual_disk_image#Dynamic_Storage_Growth" target="_blank">Almacenamiento/Crecimiento dinámico</a>.</li>
<li><em><a href="http://en.wikipedia.org/wiki/Qcow2" target="_blank">Copy-On-Write</a></em> (en este caso se trata de la posibilidad de tener una imagen &#8220;base&#8221; en modo sólo lectura y guardar las diferencias en otra imagen).</li>
<li>Gestionar <em><a href="http://en.wikipedia.org/wiki/Snapshot_(computer_storage)" target="_blank">snapshots</a> </em>del disco de cualquier momento dado.</li>
<li>Compresión al vuelo.</li>
<li>Encriptación.</li>
<li>etc.</li>
</ul>
<p>Es aquí donde cada solución de virtualización <a href="http://en.wikipedia.org/wiki/Virtual_disk_image" target="_blank">tiene su propio formato</a> para obtener todas o algunas de estas ventajas, según el caso:</p>
<ul>
<li><a href="http://www.virtualbox.org" target="_blank">VirtualBox</a> tiene al formato <a href="http://en.wikipedia.org/wiki/VirtualBox#Virtual_Desktop_Image" target="_blank">VDI</a>,</li>
<li><a href="http://www.vmware.com" target="_blank">VMWare</a> tiene el <a href="http://en.wikipedia.org/wiki/VMDK" target="_blank">VMDK</a>,</li>
<li><a href="http://www.linux-kvm.com/" target="_blank">KVM+QEmu</a> tiene el <a href="http://people.gnome.org/~markmc/qcow-image-format.html" target="_blank">QCow2</a>,</li>
<li>etc.</li>
</ul>
<p>El manejo del almacenamiento en forma dinámica de éstos nos permite que al momento de crear una imagen de un disco de por ejemplo, 80 GB, la imagen ocupe físicamente unos pocos cientos de bytes; a medida que se van guardando archivos en el disco de la VM, éstos son almacenados finalmente en el archivo de imagen, hasta llegar al tope estipulado al momento de crear la imagen de disco (los 80 GB, por ejemplo).</p>
<p>Pero volvamos al caso de la generación de una imagen de un disco físico de un equipo, ¿qué pasa si éste era de 160 GB y sólo tenía 20 GB de información guardada en uso efectivo? El archivo .raw es una copia bit a bit del disco de punta a punta, por lo tanto, su imagen Raw (&#8220;cruda&#8221;) en el Host ocupará 160 GB. Es decir, <strong>este mecanismo no discrimina el espacio ocupado por los archivos de datos del no utilizado y/o de archivos eliminados</strong>.</p>
<p>Bueno entonces, ¿para qué tenemos los formatos de imágenes nativos del <em>hypervisor </em>(KVM+QEmu en nuestro caso) que mencionamos anteriormente? ¿Es posible convertir una imagen Raw en una QCow2, para que su imagen ocupe los 20 GB de datos en vez de 160 GB? Sí es posible la conversión; para todas las operaciones con imágenes de disco KVM+QEmu tiene la herramienta <a href="http://wiki.qemu.org/download/qemu-doc.html#disk_005fimages" target="_blank">qemu-img</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ qemu-img convert <span style="color: #660033;">-f</span> raw imagen.raw <span style="color: #660033;">-O</span> qcow2 imagen.qcow2</pre></div></div>

<p>Con ese comando convertimos el archivo Raw al formato QCow2, buscando que la imagen a utilizar sea más pequeña , pero en su lugar la mejora de espacio es mucho menor a la esperada (aún si se llegara a dar). Es aquí donde nos encontraremos con un problema: <strong>¡qemu-img no sabe distinguir entre los archivos de datos y el espacio no utilizado/eliminado!</strong> Si la máquina física estuvo en uso por algún tiempo, es probable que no lleguemos ni cerca al archivo &#8220;ideal&#8221; de 20 GB. Si momentáneamente tuve en ese disco de esa máquina física 60 GB extras de música y fotos familiares, seguramente el archivo QCow2 convertido desde Raw no va a bajar de los 80GB, por ejemplo.</p>
<p>¿Y esto porqué sucede? <a href="http://en.wikipedia.org/wiki/Data_remanence" target="_blank">La teoría</a> dice que:</p>
<ul>
<li>Todo aquel espacio de disco, que viene de fábrica digamos, está compuesto de bytes en cero (0&#215;00).</li>
<li>Todo aquel espacio de disco que es utilizado primero y luego borrado del disco, no es eliminado físicamente, es decir, no vuelve a cero, sino que queda con el contenido previo. El sistema de archivos en la enorme mayoría de los casos, para ganar velocidad (y mucha) al hacerlo, sólo quita la referencia en el índice del Sistema de Archivos al conjunto de clusters del disco que tiene el contenido real del archivo. Es por eso que uno &#8220;no ve&#8221; al archivo recientemente eliminado porque el índice de archivos existentes no lo tiene más, pero físicamente el archivo sigue estando.</li>
<li>QEmu-img reconoce como espacio vacío los bytes en cero.</li>
</ul>
<p>Sin embargo, tenemos opciones para hacer lo que queremos y no quedarnos sin espacio en el Host rápidamente, nada más que en KVM+QEmu <a href="http://qemu-forum.ipi.fi/viewtopic.php?t=2739" target="_blank">hay que hacerlo</a> <a href="http://itpro.haqida.uz/d/admin-notes/20-how-to-shrink-qcow-file.html" target="_blank">un poco</a> <a href="http://kerneltrap.org/mailarchive/linux-kvm/2009/3/22/5215854/thread" target="_blank">más a mano</a>; este proceso se llama en inglés &#8220;<em>Image Shrinking</em>&#8220; (&#8220;achicar&#8221;, &#8220;reducir&#8221;, &#8220;contraer&#8221; la imagen). <a href="#3">[3]</a><a href="#4">[4]</a></p>
<h2>Achicando (&#8220;Shrinkeando&#8221;) imágenes de discos virtuales</h2>
<p>Según &#8220;la teoría&#8221; y los <a href="http://qemu-forum.ipi.fi/viewtopic.php?t=2739" target="_blank">links</a> <a href="http://itpro.haqida.uz/d/admin-notes/20-how-to-shrink-qcow-file.html" target="_blank">que se han citado</a><a href="http://kerneltrap.org/mailarchive/linux-kvm/2009/3/22/5215854/thread" target="_blank"> </a>, <strong>para poder recuperar espacio ocupado del disco hay que ponerlo en cero</strong>; ¿Y cómo se hace? Fácil, <strong>creando un archivo tan grande como el espacio remanente del disco lleno de ceros</strong>.</p>
<h3>Armando el Caso de Prueba</h3>
<p>Vamos a tratar de reproducir el problema y solucionarlo en forma representativa con una imagen Raw de 10 MB, como para que cualquiera pueda seguir estos pasos y entender de qué se trata todo esto.</p>
<p>1) Creamos una imagen Raw de prueba con 10 MB de bytes aleatorios:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">marcelo@marcelo-laptop:~$ dd if=/dev/urandom of=test.raw bs=1024 count=10000
10000+0 registros de entrada
10000+0 registros de salida
10240000 bytes (10 MB) copiados, 2,24907 s, 4,6 MB/s
marcelo@marcelo-laptop:~$</pre></div></div>

<p>2) Ya que todo disco tiene una tabla de particiones, se la creamos con parted:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">marcelo@marcelo-laptop:~$ parted test.raw print
AVISO: Usted no es el superusuario. Compruebe los permisos.
Error: /home/marcelo/test.raw: etiqueta de disco no reconocida
marcelo@marcelo-laptop:~$ parted test.raw mktable msdos
AVISO: Usted no es el superusuario. Compruebe los permisos.
marcelo@marcelo-laptop:~$ parted test.raw print
AVISO: Usted no es el superusuario. Compruebe los permisos.
Modelo:  (file)
Disco /home/marcelo/test.raw: 10,2MB
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. msdos
&nbsp;
Numero  Inicio  Fin  Tamaño  Tipo  Sistema de ficheros  Banderas
&nbsp;
marcelo@marcelo-laptop:~$</pre></div></div>

<p>El &#8220;parted test.raw print&#8221; muestra la tabla de particiones, y el &#8220;parted test.raw mktable msdos&#8221; crea una tabla de particiones de tipo MSDOS (hay otros tipos, como por ejemplo <a href="http://en.wikipedia.org/wiki/GUID_Partition_Table" target="_blank">GUID</a>). Primero vemos que el print da un error, luego creamos la tabla y por último vemos la tabla de particiones sin particiones definidas.</p>
<p>3) Ahora hay que crear una partición en esa tabla, nuevamente con parted:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">marcelo@marcelo-laptop:~$ parted test.raw mkpart primary 0 10
AVISO: Usted no es el superusuario. Compruebe los permisos.
Aviso: La partición resultante no está debidamente alineada para el mejor rendimiento.
Descartar/Ignore/Cancelar/Cancel? Ignore
marcelo@marcelo-laptop:~$ parted test.raw print
AVISO: Usted no es el superusuario. Compruebe los permisos.
Modelo:  (file)
Disco /home/marcelo/test.raw: 10,2MB
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. msdos
&nbsp;
Numero  Inicio  Fin     Tamaño  Tipo     Sistema de ficheros  Banderas
 1      512B    10,2MB  10,2MB  primary
&nbsp;
marcelo@marcelo-laptop:~$</pre></div></div>

<p>4) Ahora le damos formato a la partición en la imagen, por ejemplo, NTFS. El parámetro &#8220;&#8211;fast&#8221; es para que no llene de ceros la partición al momento de crearla (sólo para que siga con datos aleatorios) y el &#8220;&#8211;force&#8221; es para que se haga la operación a pesar de que el archivo no es un disco &#8220;de verdad&#8221;.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">marcelo@marcelo-laptop:~$ mkfs.ntfs --fast --force test.raw
test.raw is not a block device.
mkntfs forced anyway.
The sector size was not specified for test.raw and it could not be obtained automatically.  It has been set to 512 bytes.
The partition start sector was not specified for test.raw and it could not be obtained automatically.  It has been set to 0.
The number of sectors per track was not specified for test.raw and it could not be obtained automatically.  It has been set to 0.
The number of heads was not specified for test.raw and it could not be obtained automatically.  It has been set to 0.
Cluster size has been automatically set to 4096 bytes.
To boot from a device, Windows needs the 'partition start sector', the 'sectors per track' and the 'number of heads' to be set.
Windows will not be able to boot from this device.
Creating NTFS volume structures.
mkntfs completed successfully. Have a nice day.
marcelo@marcelo-laptop:~$ parted test.raw print
AVISO: Usted no es el superusuario. Compruebe los permisos.
Modelo:  (file)
Disco /home/marcelo/test.raw: 10,2MB
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. loop
&nbsp;
Numero  Inicio  Fin     Tamaño  Sistema de ficheros  Banderas
 1      0,00B   10,2MB  10,2MB  ntfs
&nbsp;
marcelo@marcelo-laptop:~$</pre></div></div>

<p>6) Perfecto, ya tenemos nuestro &#8220;mini disco&#8221; NTFS para jugar. Ahora vamos a montarlo y ver qué tiene:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">marcelo@marcelo-laptop:~$ sudo mount -o loop test.raw /mnt
[sudo] password for marcelo:
marcelo@marcelo-laptop:~$ mount
/dev/sda1 on / type ext4 (rw,errors=remount-ro)
[...]
/dev/loop0 on /mnt type fuseblk (rw,nosuid,nodev,allow_other,blksize=4096)
marcelo@marcelo-laptop:~$ tail /var/log/syslog
[...]
Aug 14 02:28:57 marcelo-laptop ntfs-3g[19770]: Version 2010.3.6 external FUSE 28
Aug 14 02:28:57 marcelo-laptop ntfs-3g[19770]: Mounted /dev/loop0 (Read-Write, label &quot;&quot;, NTFS 3.1)
Aug 14 02:28:57 marcelo-laptop ntfs-3g[19770]: Cmdline options: rw
Aug 14 02:28:57 marcelo-laptop ntfs-3g[19770]: Mount options: rw,silent,allow_other,nonempty,relatime,fsname=/dev/loop0,blkdev,blksize=4096
Aug 14 02:28:57 marcelo-laptop ntfs-3g[19770]: Ownership and permissions disabled, configuration type 1
marcelo@marcelo-laptop:~$  ls -l /mnt
total 0
marcelo@marcelo-laptop:~$</pre></div></div>

<p>7) Ahora estamos como si hubiéramos hecho el dd de un disco físico en nuestro Host con KVM+QEmu. Como se ha visto, la imagen no tiene nada en el sistema de archivos pero físicamente está lleno de bytes aleatorios y ocupa 10 MB, el tamaño completo. ¿Qué pasa si lo convertimos a QCow2? ¿Se cumple &#8220;la teoría&#8221;?</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">marcelo@marcelo-laptop:~$ sudo umount /mnt
marcelo@marcelo-laptop:~$ qemu-img convert -f raw test.raw -O qcow2 test.qcow2
marcelo@marcelo-laptop:~$ ls -l
[...]
-rw-r--r--  1 marcelo marcelo 10420224 2010-08-14 02:37 test.qcow2
-rw-r--r--  1 marcelo marcelo 10240000 2010-08-14 02:28 test.raw
[...]
marcelo@marcelo-laptop:~$ qemu-img info test.raw
image: test.raw
file format: raw
virtual size: 9.8M (10240000 bytes)
disk size: 9.8M
marcelo@marcelo-laptop:~$ qemu-img info test.qcow2
image: test.qcow2
file format: qcow2
virtual size: 9.8M (10240000 bytes)
disk size: 9.8M
cluster_size: 65536
marcelo@marcelo-laptop:~$</pre></div></div>

<p>Sí, se cumple&#8230; es más, la imagen QCow2 ocupa más espacio que la Raw (por ahora). Hemos podido reproducir el problema.</p>
<h3>Llenando de Ceros el espacio vacío &#8211; Wiper.py</h3>
<p>Bien, ahora se me ocurrió armar un script en Python para que me ayude a automatizar el proceso de crear un archivo con ceros hasta que me quede sin espacio para luego borrarlo. Lo llamé &#8220;wiper.py&#8221;. El código fuente es el siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># coding: utf-8</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Wiper</span>
<span style="color: #808080; font-style: italic;"># Copyleft 2010 - Licencia BSD</span>
<span style="color: #808080; font-style: italic;"># Autor: Marcelo Fernández.</span>
<span style="color: #808080; font-style: italic;"># Email: marcelo.fidel.fernandez@gmail.com</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># This script creates a file which fills the available disk with zero bytes,</span>
<span style="color: #808080; font-style: italic;"># and when the disk is full, the file is deleted.</span>
<span style="color: #808080; font-style: italic;"># This allow to convert a raw partition to qcow2 'shrinking' the real image</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>, <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">errno</span>
&nbsp;
FILENAME = <span style="color: #483d8b;">'wiper.000'</span>
STEP_SIZE = <span style="color: #ff4500;">4096</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">2</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'usage: python wiper.py path_mounted_image'</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    fat_file_path = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, FILENAME<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        fat_file = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>fat_file_path, <span style="color: #483d8b;">'wb'</span>, STEP_SIZE<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span>, e:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'There was an error opening the file in %s: %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>fat_file_path, <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>e<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Temp file %s open for writing. Filling disk...'</span> <span style="color: #66cc66;">%</span> fat_file_path
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
            fat_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00'</span> <span style="color: #66cc66;">*</span> STEP_SIZE<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">EnvironmentError</span>, env_error:
        <span style="color: #ff7700;font-weight:bold;">if</span> env_error.<span style="color: #dc143c;">errno</span> == <span style="color: #dc143c;">errno</span>.<span style="color: black;">ENOSPC</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'No space left on device, good! Deleting temp file...'</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #808080; font-style: italic;"># There was another error different from 'No space available',</span>
            <span style="color: #808080; font-style: italic;"># anyway we'll alway try to delete the fat_file</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Abnormal error: '</span>, oserror
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span>, e:
        <span style="color: #808080; font-style: italic;"># Rarely, but this could happend too</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Exception: '</span> + <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span>e<span style="color: black;">&#41;</span>
    fat_file.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #dc143c;">os</span>.<span style="color: black;">unlink</span><span style="color: black;">&#40;</span>fat_file_path<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span>, e:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'There was a problem deleting the temp file.'</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Temp file erased ok.'</span></pre></div></div>

<p>Básicamente hace lo necesario, el STEP_SIZE es importante para que la operación sea bastante más rápida que escribiendo de a un byte. Vamos a ejecutar el script y convertir nuevamente el archivo Raw a QCow2 con qemu-img a ver qué sucede:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">marcelo@marcelo-laptop:~$ sudo mount -o loop test.raw /mnt
marcelo@marcelo-laptop:~$ python wiper.py /mnt/
Temp file /mnt/wiper.000 open for writing. Filling disk...
No space left on device, good! Deleting temp file...
Temp file erased ok.
marcelo@marcelo-laptop:~$ ls -l /mnt
total 0
marcelo@marcelo-laptop:~$ sudo umount /mnt
marcelo@marcelo-laptop:~$ qemu-img convert -f raw test.raw -O qcow2 test_shrinked.qcow2
marcelo@marcelo-laptop:~$ ls -l
[...]
-rw-r--r--  1 marcelo marcelo 10420224 2010-08-14 02:42 test.qcow2
-rw-r--r--  1 marcelo marcelo 10240000 2010-08-14 02:58 test.raw
-rw-r--r--  1 marcelo marcelo  3014656 2010-08-14 02:58 test_shrinked.qcow2
marcelo@marcelo-laptop:~$ sudo mount -o loop test.raw /mnt
marcelo@marcelo-laptop:~$ df -h
S.ficheros            Tamaño Usado  Disp Uso% Montado en
/dev/sda1              16G  6,7G  7,7G  47% /
[...]
/home/marcelo/test.raw
                      9,8M  2,5M  7,3M  26% /mnt
marcelo@marcelo-laptop:~$</pre></div></div>

<p>Bueno, ahora sí, el archivo QCow2 ocupa un cuarto del archivo Raw (2,5 MB). ¿En qué se gastan estos 2.5MB? Seguramente en los índices del sistema de archivos para poder gestionar el espacio libre. Es altamente probable que más que este espacio recuperado no podamos ganar, ya que si tocamos estos índices, corrompemos el sistema de archivos; recordemos que en test.raw puede haber un Sistema Operativo completo con todos sus archivos de datos.</p>
<p>De todas maneras, esto puede variar según el sistema de archivos de la imagen (NTFS en este caso) y los parámetros con los cuales se está manejando el mismo (el tamaño de bloque y de cluster incide mucho en el espacio que ocupan los índices de los Sistemas de Archivos en general).</p>
<h2>Conclusiones</h2>
<p>Es bueno saber que también se puede usar el comando dd para crear un archivo lleno de ceros en la partición ntfs de pruebas montada, con el comando &#8220;dd if=/dev/zero of=/mnt/borrame.000&#8243; y después borrar el archivo en cuestión, pero puede hacerse interminable el &#8220;llenado&#8221; si no pasamos como parámetro un block size relativamente grande, como de 4096 bytes:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">marcelo@marcelo-laptop:~$ time dd if=/dev/zero of=/mnt/borrame.000 bs=4096
dd: escribiendo «/mnt/borrame.000»: No hay espacio libre en el dispositivo
1863+0 registros de entrada
1862+0 registros de salida
7626752 bytes (7,6 MB) copiados, 0,144428 s, 52,8 MB/s
&nbsp;
real	0m0.149s
user	0m0.000s
sys	0m0.030s
marcelo@marcelo-laptop:~$</pre></div></div>

<p>Prueben a pasarle bs=1, a ver cuánto tarda&#8230;. (lo pueden cortar con Ctrl+C). <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Una cuestión más que queda dando vueltas es que esta situación de espacio desperdiciado por la imagen se da también luego de un tiempo de usar la Máquina Virtual, si se da el caso de que se libere espacio en forma masiva; como caso, el ejemplo de un disco de 80 GB con 20 GB dedicados al Sistema Operativo más 60 GB de fotos y música eliminados recientemente.  Aquí también será útil correr wiper.py en la imagen montada y volver a ejecutar &#8220;qemu-img convert&#8221; para <em>shrinkear</em> la imagen.</p>
<p>En fin, espero que este post le sea de utilidad a aquellos que trabajamos con tan formidable <em>hypervisor</em> como lo es KVM y su gestor de I/O como lo es QEmu.</p>
<p>Saludos</p>
<p><a id="1">[1]</a> Si bien a un Linux se lo puede consolidar más fácilmente, sólo copiando todos los archivos con rsync, o &#8220;cp -a&#8221;, con Windows este método no funciona, y hay que copiar el disco o al menos la partición completa. La idea al usar dd es abstraerse del SO.<br />
<a id="2">[2]</a> En vez de dd se puede usar una herramienta de clonación de discos/particiones que &#8220;entienda&#8221; o &#8220;interprete&#8221; el filesystem, como <a href="http://www.partimage.org/Main_Page" target="_blank">Partimage</a> para intentar generar directamente una imagen Raw con el espacio no utilizado en cero; pero nunca lo probé, ni me parece un método muy &#8220;limpio&#8221;, ya que estamos insertando un software algo complejo en el medio de algo que de cualquier otra manera es conceptualmente simple y repetible. En el único caso que lo probaría es si estoy falto de espacio de disco en el Host. Si alguien lo prueba, me avisa. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
<a id="3">[3]</a> Creo que &#8220;comprimir&#8221; no es la palabra apropiada porque da la idea al lector de que hay un proceso (que implementa un algoritmo) de <a href="http://en.wikipedia.org/wiki/Data_compression" target="_blank">compresión de datos</a> sin pérdida, como por ejemplo, <a href="http://en.wikipedia.org/wiki/Lempel-Ziv" target="_blank">LZ</a>. Sin embargo, aquí lo que se necesita es recuperar el espacio no utilizado de la imagen, para obtener un tamaño de imagen menor.<br />
<a id="4">[4]</a> Como nota al margen, VMWare tiene en sus VMWare Tools una opción para hacer &#8220;Shrink&#8221; de la imagen, pero ¿cómo se divierte un Sysadmin con ganas de aprender si sólo tiene que hacer click en un botón que diga &#8220;Shrink Image&#8221;? <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/08/achicando-imagenes-de-maquinas-virtuales-kvm-qcow2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free Pascal y Lazarus en Ubuntu</title>
		<link>http://blog.marcelofernandez.info/2010/06/free-pascal-y-lazarus-en-ubuntu/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=free-pascal-y-lazarus-en-ubuntu</link>
		<comments>http://blog.marcelofernandez.info/2010/06/free-pascal-y-lazarus-en-ubuntu/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 11:00:18 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=898</guid>
		<description><![CDATA[Creo que la gran mayoría de los programadores debemos recordar aquellos primeros momentos en que uno pasaba tardes y noches enteras escribiendo y escribiendo líneas de código en aquellas XT, AT, Commodores 64/128, etc., sólo por amor al arte y puro fanatismo. Supongo que diríamos lo mismo de los primeros años de facultad, cuando en [...]]]></description>
			<content:encoded><![CDATA[<p>Creo que la gran mayoría de los programadores debemos recordar aquellos primeros momentos en que uno pasaba tardes y noches enteras escribiendo y escribiendo líneas de código en aquellas XT, AT, Commodores 64/128, etc., sólo por amor al arte y puro fanatismo. Supongo que diríamos lo mismo de los primeros años de facultad, cuando en materias de título &#8220;Programación I&#8221; uno repasaba el paradigma de la <a href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_estructurada" target="_blank">Programación Estructurada</a>, casi siempre en el lenguaje de aprendizaje facultativo por excelencia, al menos acá en Argentina: <strong><a href="http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_Pascal" target="_blank">Pascal</a></strong>, usando <a href="http://en.wikipedia.org/wiki/Turbo_pascal" target="_blank">Turbo Pascal</a>, su versión más popular.</p>
<p>Viniendo más acá en el tiempo, y buscando alguna herramienta donde aprovechar mis conocimientos de este lenguaje pero para desarrollar sobre Linux, supe de la existencia de <a href="http://freepascal.org/" target="_blank">Free Pascal</a>, un compilador Pascal libre, multiplataforma y con soporte a diferentes arquitecturas, que genera ejecutables binarios con dependencias mínimas. También estaba disponible <a href="http://www.lazarus.freepascal.org/" target="_blank">Lazarus</a>, su inseparable IDE, no casualmente muy parecido a <a href="http://en.wikipedia.org/wiki/CodeGear_Delphi" target="_blank">Delphi</a>.</p>
<p>El problema era que hasta Ubuntu 9.04 y por una cuestión de madurez, las bibliotecas gráficas de Lazarus aún dependían de GTK 1.2 ( completamente en desuso desde hace &#8220;siglos&#8221; en las distribuciones Linux), y se veía así:</p>
<p style="text-align: center;"><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Lazarus_IDE_GTK1_Linux.png"><img class="aligncenter size-medium wp-image-899" title="Lazarus IDE sobre GTK1" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Lazarus_IDE_GTK1_Linux-300x225.png" alt="" width="300" height="225" /></a></p>
<p>Se veía &#8220;duro&#8221;, anticuado y lejos de toda amigabilidad con el usuario programador, carente de características básicas hoy en día tales como <a href="http://es.wikipedia.org/wiki/Unicode" target="_blank">Unicode</a>, <a href="http://es.wikipedia.org/wiki/Antialiasing" target="_blank">antialiasing</a> y mucho más&#8230; por lo tanto, concluí en ese momento que uno no podía encarar ningún desarrollo nuevo para Linux/Unix usando GTK 1.2 (y por ende Free Pascal+Lazarus), sucedido por la versión 2.0 allá por el año 2002.</p>
<p>En estos días leí un mail en la lista de <a href="http://ubuntu-ar.org/" target="_blank">Ubuntu-Ar</a> sobre Lazarus y Free Pascal, y decidí a instalarlo para echarle un vistazo otra vez. Por suerte la situación cambió bastante, me encontré con un bonito e importante cambio:</p>
<p style="text-align: center;"><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo1.png"><img class="aligncenter size-medium wp-image-900" title="Lazarus sobre GTK 2" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo1-300x187.png" alt="" width="300" height="187" /></a></p>
<p>Ahora, con Lazarus sobre GTK 2, ¡sí que está mucho más decente! Junto a <a href="http://es.wikipedia.org/wiki/Gambas" target="_blank">Gambas</a> es lo más parecido a un entorno <a href="http://es.wikipedia.org/wiki/Desarrollo_r%C3%A1pido_de_aplicaciones" target="_blank">RAD</a> &#8220;estilo Visual Basic&#8221; que hay dando vueltas para Linux. Y es aún mejor que éstos dos:</p>
<ul>
<li>Libre: <a href="http://freepascal.org/faq.var#general-license" target="_blank">Licencia LGPL</a> (salvo el compilador que es GPL). Permite desarrollar software con cualquier licencia, incluso comercial.</li>
<li>Gratuito: Viene con los fuentes de sí mismo ¡y se <a href="http://en.wikipedia.org/wiki/Self-hosting">compila a sí mismo</a>!</li>
<li>Multiplataforma: DOS, Linux, Windows, Mac OSX, FreeBSD, Solaris, y <a href="http://freepascal.org/docs-html/user/userse2.html#x5-40001.2" target="_blank">más</a>.</li>
<li>Soporte de diferentes arquitecturas: Intel, AMD64, ARM, PowerPC, Sparc&#8230;</li>
<li>Diferentes Toolkits GUI: Win32/Win64, GTK1/2, QT3/4, Carbon, Cocoa, (aunque en diferentes estados de madurez).</li>
<li>Compatibilidad en <a href="http://wiki.lazarus.freepascal.org/Lazarus_For_Delphi_Users/es">un alto porcentaje</a> con Object Pascal y Delphi.</li>
</ul>
<p>Por último, me hice un &#8220;Hola Mundo&#8221; muy muy sencillo y lo compilé. Luego, ejecuté el comando <a href="http://linux.about.com/library/cmd/blcmdl1_ldd.htm" target="_blank">ldd</a>, para saber de qué bibliotecas dependía. El binario, que ocupaba 14 MB (ojo, era todo info de debug, luego de pasarle un <a href="http://www.computerhope.com/unix/strip.htm" target="_blank">strip</a> ocupó 5.1 MB) dependía de esto:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">marcelo<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:<span style="color: #000000; font-weight: bold;">/</span>tmp$ <span style="color: #c20cb9; font-weight: bold;">ldd</span> project1
	linux-vdso.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span>  <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007fff441ff000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libX11.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libX11.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6603e2f000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgdk_pixbuf-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgdk_pixbuf-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6603c13000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgtk-x11-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgtk-x11-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66035f0000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgdk-x11-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgdk-x11-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6603343000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgobject-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgobject-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66030fb000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libglib-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libglib-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6602e1c000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgthread-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgthread-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6602c17000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgmodule-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgmodule-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6602a13000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpango-1.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpango-1.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66027c8000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpthread.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpthread.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66025ab000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libatk-1.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libatk-1.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f660238a000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libcairo.so.2 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libcairo.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6602106000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libdl.so.2 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libdl.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601f02000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libc.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libc.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601b80000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libxcb.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libxcb.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601963000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgio-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgio-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66016b0000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	librt.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>librt.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66014a8000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libm.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libm.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601224000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXext.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXext.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601012000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXrender.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXrender.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6600e08000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXinerama.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXinerama.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6600c04000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXi.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXi.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66009f4000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXrandr.so.2 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXrandr.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66007eb000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXcursor.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXcursor.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66005e0000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpangocairo-1.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpangocairo-1.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66003d3000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXcomposite.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXcomposite.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66001d0000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXdamage.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXdamage.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fffcc000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXfixes.so.3 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXfixes.so.3 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ffdc6000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpangoft2-1.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpangoft2-1.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ffb9c000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libfreetype.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libfreetype.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff915000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libz.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libz.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff6fe000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libfontconfig.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libfontconfig.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff4c9000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpcre.so.3 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpcre.so.3 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff29a000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">/</span>lib64<span style="color: #000000; font-weight: bold;">/</span>ld-linux-x86-64.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6604184000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpixman-1.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpixman-1.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff041000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libdirectfb-1.2.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libdirectfb-1.2.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fedbd000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libfusion-1.2.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libfusion-1.2.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65febb3000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libdirect-1.2.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libdirect-1.2.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe99a000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpng12.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpng12.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe772000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libxcb-render-util.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libxcb-render-util.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe56e000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libxcb-render.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libxcb-render.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe365000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXau.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXau.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe160000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXdmcp.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXdmcp.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fdf5a000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libresolv.so.2 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libresolv.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fdd41000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libselinux.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libselinux.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fdb22000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libexpat.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libexpat.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fd8f9000<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Si bien 5 MB sigue siendo un poco mucho (y no incluye GTK ni nada, aunque no jugué con las opciones del compilador) para un simple binario, a partir de ahora FreePascal + Lazarus en mi ranking personal entran en la categoría de &#8220;interesantes&#8221; <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Es bastante tarde, es cierto, más cuando gracias a <a href="http://www.python.org" target="_blank">Python</a> disfruto y me divierto al programar; tengo todo lo que necesito y más que lo que podría tener con FreePascal + Lazarus (siempre lo digo, Python no sería Python si no fuera por <a href="http://www.python.com.ar/" target="_blank">PyAr</a>), pero&#8230; bueno, rescato y festejo que haya otra herramienta de desarrollo libre, potente y al alcance de cualquiera. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/06/free-pascal-y-lazarus-en-ubuntu/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sincronizar carpetas a un Servidor Casero automáticamente</title>
		<link>http://blog.marcelofernandez.info/2010/06/sincronizar-carpetas-a-un-servidor-casero-automaticamente/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sincronizar-carpetas-a-un-servidor-casero-automaticamente</link>
		<comments>http://blog.marcelofernandez.info/2010/06/sincronizar-carpetas-a-un-servidor-casero-automaticamente/#comments</comments>
		<pubDate>Fri, 18 Jun 2010 11:00:46 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=837</guid>
		<description><![CDATA[Introducción Supongamos que tengo un equipo donde usualmente estoy trabajando y otro equipo que está siempre encendido, ambos separados por Internet. En este último, el único puerto abierto sobre una IP Pública es el 22 para usar SSH, con lo cual me viene perfecta la capacidad de rsync de sincronizar carpetas y los últimos cambios mientras [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción</h2>
<p>Supongamos que tengo un equipo donde usualmente estoy trabajando y otro equipo que está siempre encendido, ambos separados por Internet. En este último, el único puerto abierto sobre una IP Pública es el 22 para usar <a href="http://www.openssh.com/" target="_blank">SSH</a>, con lo cual me viene perfecta la capacidad de <a href="http://samba.anu.edu.au/rsync/" target="_blank">rsync</a> de sincronizar carpetas y los últimos cambios mientras estoy trabajando, todo mediante un canal seguro.</p>
<h2>El Script de sincronización</h2>
<p>Lo único que necesito es este script en la carpeta personal de mi equipo &#8220;cliente&#8221;, o sea, donde hago mis quehaceres diarios:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #666666; font-style: italic;"># Script para sincronización a Servidor vía Casero rsync/ssh.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Copyleft 2010 - Licencia BSD</span>
<span style="color: #666666; font-style: italic;"># Autor: Marcelo Fernández.</span>
<span style="color: #666666; font-style: italic;"># Email: marcelo.fidel.fernandez@gmail.com</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Características:</span>
<span style="color: #666666; font-style: italic;">#  - Guarda la salida en un archivo de log (~/sync.log).</span>
<span style="color: #666666; font-style: italic;">#  - Sincronización de una vía; pisa las modificaciones (y elimina) en el destino.</span>
<span style="color: #666666; font-style: italic;">#  - Envía notificaciones al escritorio del usuario.</span>
<span style="color: #666666; font-style: italic;">#  - Se sugiere ser llamado desde cron (gnome-schedule para el usuario final).</span>
<span style="color: #666666; font-style: italic;">#  - Sincroniza (una sola vía) el directorio Documentos de mi Carpeta Personal y el Escritorio,</span>
<span style="color: #666666; font-style: italic;">#    se pueden agregar más carpetas a gusto al momento de ejecutar el comando rsync.</span>
<span style="color: #666666; font-style: italic;">#    También debe personalizarse el destino del backup, ahora en /media/Disco1/Backup</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Requerimientos:</span>
<span style="color: #666666; font-style: italic;">#  - Rsync</span>
<span style="color: #666666; font-style: italic;">#  - Paquete libnotify-bin (Debian/Ubuntu), que brinda el comando notify-send.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Parámetros:</span>
<span style="color: #666666; font-style: italic;">#  - Host destino. El script se lo llama &quot;./sync.sh mi_host&quot;.</span>
<span style="color: #666666; font-style: italic;">#    El login debe ser vía public keys, y la passphrase la maneja Gnome.</span>
&nbsp;
<span style="color: #007800;">HOST</span>=$<span style="color: #000000;">1</span>
<span style="color: #007800;">LOG_FILE</span>=<span style="color: #ff0000;">&quot;sync.log&quot;</span>
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">DISPLAY</span>=:<span style="color: #000000;">0.0</span> <span style="color: #666666; font-style: italic;"># Para el notify</span>
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">SSH_AUTH_SOCK</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$(find /tmp/keyring*/ -perm 0755 -type s -user $LOGNAME -group $LOGNAME -name '*ssh' | head -n 1)</span>&quot;</span>
&nbsp;
notify-send <span style="color: #660033;">-u</span> normal <span style="color: #660033;">--icon</span>=gtk-refresh <span style="color: #660033;">--category</span>=transfer <span style="color: #ff0000;">&quot;Sincronizando a Casa...&quot;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span><span style="color: #000000; font-weight: bold;">`</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #007800;">$LOG_FILE</span>
rsync <span style="color: #660033;">-avz</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'ssh'</span> <span style="color: #660033;">--delete</span> ~<span style="color: #000000; font-weight: bold;">/</span>Documentos ~<span style="color: #000000; font-weight: bold;">/</span>Escritorio <span style="color: #007800;">$HOST</span>:<span style="color: #000000; font-weight: bold;">/</span>media<span style="color: #000000; font-weight: bold;">/</span>Disco1<span style="color: #000000; font-weight: bold;">/</span>Backup<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #000000; font-weight: bold;">&amp;&gt;&gt;</span> <span style="color: #007800;">$LOG_FILE</span>
<span style="color: #007800;">RETVAL</span>=<span style="color: #007800;">$?</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$RETVAL</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
    notify-send <span style="color: #660033;">-u</span> critical <span style="color: #660033;">--icon</span>=gtk-dialog-error <span style="color: #660033;">--category</span>=transfer.error  <span style="color: #ff0000;">&quot;Error al Sincronizar&quot;</span>;
<span style="color: #000000; font-weight: bold;">else</span>
    notify-send <span style="color: #660033;">-u</span> normal <span style="color: #660033;">--icon</span>=gtk-apply <span style="color: #660033;">--category</span>=transfer.complete <span style="color: #ff0000;">&quot;Sincronización Completa&quot;</span>;
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<h2>Programando su ejecución automática</h2>
<p>Este script está pensado y preparado para ser llamado desde la aplicación &#8220;<a href="http://gnome-schedule.sourceforge.net/" target="_blank">Tareas Programadas</a>&#8221; de Gnome (disponible en el Centro de Software de Ubuntu o se instala haciendo click <a href="apt://gnome-schedule">aquí</a>):</p>
<p style="text-align: center;"><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo.png"><img class="size-medium wp-image-851 aligncenter" title="Programador de Tareas 1" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-300x72.png" alt="" width="300" height="72" /></a></p>
<p style="text-align: left;"><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo.png"></a>Este es el detalle de la configuración de la tarea:</p>
<p><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-3.png"><img class="size-medium wp-image-852 aligncenter" title="Programador de Tareas 2" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-3-300x283.png" alt="" width="300" height="283" /></a></p>
<p style="text-align: center;">
<p>Y además nos avisa de que está trabajando y si tuvo éxito o no al sincronizar:</p>
<p><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-2.png"><img class="aligncenter size-full wp-image-861" title="Notificación 1" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-2.png" alt="" width="340" height="80" /></a></p>
<p><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-1.png"><img class="aligncenter size-full wp-image-864" title="Notificacion OK" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-1.png" alt="" width="340" height="80" /></a><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-4.png"><img class="aligncenter size-full wp-image-865" title="Notificación Error" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo-4.png" alt="" width="340" height="80" /></a></p>
<h2>Algunas cuestiones para destacar</h2>
<p>Como se aclara en los comentarios, cada vez que rsync copia las modificaciones al servidor, &#8220;pisa&#8221; lo que había anteriormente, lo que comúnmente se denomina sincronización de archivos &#8220;<a href="http://en.wikipedia.org/wiki/File_synchronization" target="_blank">de una vía</a>&#8220;.</p>
<p>Lo más interesante es que a pesar de ser ejecutado desde Cron, aprovecha las llaves SSH desbloqueadas por Gnome en la sesión de escritorio del usuario, es decir que la primera sincronización, si previamente no me había conectado al equipo remoto, me pide la frase de paso para desbloquear la clave privada; a partir de ese momento ésta queda compartida, gracias al <a href="http://es.wikipedia.org/wiki/SSH-Agent" target="_blank">ssh-agent</a> que utiliza Gnome en <em>background</em>. Luego, mientras siga la sesión de escritorio establecida, va a aprovechar la llave desbloqueada por el usuario y hacer la sincronización sin mayor problema. <strong>Esto es mucho mejor en cuanto a seguridad que usar una clave privada sin frase de paso contra el servidor, y me permite desbloquearla sólo la primera vez y no cada vez que se hace la sincronización, siendo un perfecto balance (al menos para mí) entre seguridad, automatización y comodidad</strong>. Lógicamente esto sirve para utilizar en cualquier conexión SSH que se quiera establecer, y la solución, después de dar muchas vueltas y probar muchas alternativas (¡el ssh del cron no &#8220;veía&#8221; al agente!), la encontré en <a href="http://www.codealpha.net/163/cron-ssh-and-rsync-and-key-with-passphrase-ubuntu/" target="_blank">este post</a>.</p>
<h2>Conclusión</h2>
<p>Este script fue creciendo desde algo muy simple, totalmente manual y que ejecutaba &#8220;cada vez que me acordaba&#8221; a mejorarlo un poco en cuanto a la automatización y hacerlo más &#8220;lindo&#8221; como está hoy. Si bien hay muchísimos mecanismos más robustos o con más facilidades (usando los <em>snapshots</em> de rsync por ejemplo y/o sincronizando ida y vuelta), <strong>éste es el que funciona para mí</strong>. Es bien claro lo que hace y no hay ninguna &#8220;magia&#8221; en el medio; trabaja sin que me moleste en mi actividad diaria y me despreocupo totalmente de que <em>tenía</em> que hacer backup. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Espero que les sirva como a mí. <a href="http://www.vicente-navarro.com/blog/2008/01/13/backups-con-rsync/" target="_blank">Acá hay mucha más información</a> sobre rsync y una explicación más profunda de las diferentes opciones y alternativas, que por supuesto se pueden utilizar con esto como base.</p>
<p>¡Saludos!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/06/sincronizar-carpetas-a-un-servidor-casero-automaticamente/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Reiniciando las conexiones de red automáticamente en Ubuntu</title>
		<link>http://blog.marcelofernandez.info/2010/06/reiniciando-las-conexiones-de-red-automaticamente-en-ubuntu/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=reiniciando-las-conexiones-de-red-automaticamente-en-ubuntu</link>
		<comments>http://blog.marcelofernandez.info/2010/06/reiniciando-las-conexiones-de-red-automaticamente-en-ubuntu/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 11:00:43 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=816</guid>
		<description><![CDATA[Hace un tiempo que tengo una interfaz Wifi USB Encore; siempre la usé ocasionalmente, en Ubuntu se conectaba y tenía red sin problemas, pero al momento de usarla en forma constante nunca supuse que el módulo rtl8187, responsable de su funcionamiento, iba a tener tantos bugs. En Ubuntu 10.04 funciona sin instalar nada adicional, pero los [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.encore-usa.com/ar/product/ENUWI-G2"><img class="alignright size-full wp-image-827" title="Encore ENUWI-G2 - Chipset RTL8187B" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/ENUWI-G2_pdt_main_090107.png" alt="" width="216" height="187" /></a>Hace un tiempo que tengo una interfaz <a href="http://www.encore-usa.com/ar/product/ENUWI-G2" target="_blank">Wifi USB Encore</a>; siempre la usé ocasionalmente, en Ubuntu se conectaba y tenía red sin problemas, pero al momento de usarla en forma constante nunca supuse que el módulo rtl8187, responsable de su funcionamiento, <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/182473" target="_blank">iba</a> <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/225851" target="_blank">a</a> <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/293946" target="_blank">tener</a> <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/254438" target="_blank">tantos</a> <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/215802" target="_blank">bugs</a>. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </p>
<p>En Ubuntu 10.04 funciona sin instalar nada adicional, pero los principales problemas son que funciona sólo a 11Mbps y que aleatoriamente se desconecta, sin causa aparente, y el Network Manager vuelve a reconectarse. El problema es más serio cuando Network Manager se cansa de revivir a la placa, y el equipo se queda desconectado definitivamente. Y más si no estoy cerca para reconectarla a mano. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </p>
<p>Luego de probar unas cuantas recetas (y de esquivar Ndiswrapper porque es un equipo de 64 bits), decidí que voy a dejarlo así, y me hice un scriptcito de cron para reiniciar Network Manager si la interfaz está caída:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># /usr/bin/network_respawn</span>
<span style="color: #666666; font-style: italic;"># Network respawn -- rtl8187b dies randomly and despite Network-Manager usually</span>
<span style="color: #666666; font-style: italic;"># reconnects again, sometimes it gives up and dies without connection.</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># If wlan0 is not connected, it restarts Network-Manager</span>
<span style="color: #666666; font-style: italic;"># This script is meant to be called from a cron job. </span>
&nbsp;
<span style="color: #007800;">IFACE</span>=<span style="color: #ff0000;">&quot;wlan0&quot;</span>
&nbsp;
<span style="color: #007800;">CONNECTED</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #007800;">$IFACE</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<span style="color: #000000; font-weight: bold;">/</span>network<span style="color: #000000; font-weight: bold;">/</span>ifstate<span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$CONNECTED</span>&quot;</span> == <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>  <span style="color: #666666; font-style: italic;"># Disconnected. Respawning...</span>
    <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>service network-manager restart
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>Además, hay que crear el archivo en /etc/cron.d/network_respawn para que el sistema llame al script anterior, cada 3 minutos en mi caso:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Network respawn -- rtl8187b dies randomly and despite Network-Manager usually</span>
<span style="color: #666666; font-style: italic;"># reconnects again, sometimes it gives up and dies without connection.</span>
<span style="color: #666666; font-style: italic;"># If wlan0 is not connected, it restarts Network-Manager</span>
&nbsp;
<span style="color: #007800;">SHELL</span>=<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">sh</span>
<span style="color: #007800;">PATH</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>sbin:<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin:<span style="color: #000000; font-weight: bold;">/</span>sbin:<span style="color: #000000; font-weight: bold;">/</span>bin:<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>sbin:<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin
&nbsp;
<span style="color: #000000; font-weight: bold;">*/</span><span style="color: #000000;">3</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> root <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>network_respawn</pre></div></div>

<p>Es un script sencillo, y puede ser utilizado para cualquier propósito como el mío. Lo malo es que reinicia todas las conexiones del equipo, ya que reinicia el Network Manager .</p>
<p>¿A alguien se le ocurre cómo hacerlo mejor? <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/06/reiniciando-las-conexiones-de-red-automaticamente-en-ubuntu/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Discos Rígidos con Sectores de 4KB en Linux</title>
		<link>http://blog.marcelofernandez.info/2010/06/discos-rigidos-con-sectores-de-4kb-en-linux/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=discos-rigidos-con-sectores-de-4kb-en-linux</link>
		<comments>http://blog.marcelofernandez.info/2010/06/discos-rigidos-con-sectores-de-4kb-en-linux/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 02:52:03 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=710</guid>
		<description><![CDATA[Actualización (Julio 2010): Armé y redacté no tan informalmente este post en forma de artículo; el mismo está disponible para su consulta, crítica y mejoras en la sección de Publicaciones del sitio. Los nuevos discos de Western Digital En estos días tuve la oportunidad de comprar y configurar una máquina Ubuntu con un disco rígido [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Actualización (Julio 2010)</strong>: Armé y redacté no tan informalmente este post en forma de artículo; el mismo está disponible para su consulta, crítica y mejoras en la sección de <a href="http://blog.marcelofernandez.info/publicaciones/">Publicaciones</a> del sitio.</p>
<h2>Los nuevos discos de Western Digital<a href="http://www.wdc.com/en/products/products.asp?driveid=772"><img class="alignright size-full wp-image-717" title="Discos WD Caviar Green" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/wdfDesktop_CaviarGreen_SATA64.jpg" alt="" width="168" height="168" /></a></h2>
<p>En estos días tuve la oportunidad de comprar y configurar una máquina Ubuntu con un disco rígido Western Digital de 1,5 Terabytes (1500 Gigabytes aprox.); más precisamente el modelo <a href="http://www.wdc.com/en/products/products.asp?driveid=772" target="_blank">WD15EARS</a>, con 64 MB de caché, velocidad de rotación que varía entre 5400 y 7200 RPMs (llamado &#8220;<a href="http://www.wdc.com/en/flash/index.asp?family=intelliseek" target="_blank">IntelliSeek</a>&#8220;), interfaz SATA II (3 Gb/seg), y que incluye una nueva tecnología de la marca conocida como &#8220;<a href="http://www.wdc.com/en/products/advancedformat/" target="_blank">Advanced Format Drive</a>&#8221; (paper <a href="http://www.wdc.com/wdproducts/library/?id=216&amp;type=87" target="_blank">aquí</a>).</p>
<p style="text-align: left;">Si bien yo pensé que estaba comprando un disco más aunque sólo de mayor capacidad, luego al mirarlo <a href="http://techreport.com/articles.x/15769" target="_blank">más de cerca</a> en su etiqueta decía:</p>
<p style="text-align: left;"><a href="http://www.wdc.com/en/products/advancedformat/"><img class="aligncenter size-full wp-image-712" title="Tabla de Alineación y Sistemas Operativos" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/WD-Align_chart_r2.jpg" alt="" width="550" height="270" /></a></p>
<p style="text-align: left;">Resumiendo, dice que:</p>
<ul>
<li>Si va a utilizar el disco con Windows XP con una sola partición en el disco, sólo ponga el Jumper en los pins 7-8 del HD.</li>
<li>Si va a utilizar el disco con Windows XP con más de una partición en el disco, use la utilidad &#8220;WD Align&#8221;.</li>
<li><strong>Si va a utilizar otro SO (Windows Vista/7, Mac OS X, o Linux), el disco no requiere preparación adicional para el particionamiento.</strong></li>
</ul>
<p>&#8220;Bueno, total no uso Windows&#8221;, pensé. Particioné y formatié con el <a href="http://gparted.sourceforge.net/" target="_blank">GParted</a> el disco y me puse a utilizarlo normalmente. No noté nada raro, hasta que unos días después googleando sobre experiencias con éste disco y Linux me encontré con <a href="http://community.wdc.com/t5/Desktop/Problem-with-WD-Advanced-Format-drive-in-LINUX-WD15EARS/td-p/6395/" target="_blank">este hilo en el foro de WD</a> (&#8220;<em>Problem with WD Advanced Format drive in LINUX (WD15EARS)</em>&#8220;). Al parecer, mucha gente utilizando Linux con estos discos notaba una lentitud excesiva en cada cosa que hacía, como si hubiera un problema, no del hardware fallando y perdiendo datos, sino de demoras muy grandes en lectura/escritura. Resultó que <strong>aún usando Linux, el disco sí requiere preparación adicional, al contrario de lo que dice el fabricante</strong>, como veremos más adelante.</p>
<h2>Sectores de 4 KBytes en vez de 512 Bytes, ¿Por qué?</h2>
<p><a href="http://en.wikipedia.org/wiki/Cylinder-head-sector#cite_note-0" target="_blank">Desde los primeros días</a> de los discos rígidos, la mínima unidad de almacenamiento direccionable fue el <a href="http://en.wikipedia.org/wiki/Cylinder-head-sector" target="_blank">sector</a>, de <strong>512 Bytes</strong> de capacidad. Esta granularidad se eligió porque siempre fue un buen balance entre la <a href="http://elezeta.net/2004/09/16/fragmentacin-de-que-se-trata/" target="_blank">fragmentación interna</a> de los archivos<a href="#nota1">*</a> y el manejo físico del disco relativo a la corrección de errores, flags de inicio/fin del sector más la separación inter-sector (<em>gap</em>). Toda la industria de la PC y el software creado para ella se apoyó en este estándar de facto, y casi ningún utilitario, BIOSes, ni Sistema Operativo se pensaron para un posible cambio&#8230; sólo hasta hace unos pocos años.</p>
<p>Western Digital es una de las primeras marcas en sacar al mercado discos con sectores 8 veces más grandes que los anteriores, de 4 KBytes (4096 Bytes); estos discos son etiquetados como que poseen &#8220;Advanced Format Technology&#8221; (&#8220;Tecnología de Formato Avanzado&#8221;), y <strong>es lo primero que uno debería empezar a mirar al comprar discos nuevos de gran tamaño (1 TB o superior), ya sean de WD o de otros fabricantes</strong>. Casualmente (o no tanto), esto incluye al disco que compré.</p>
<p>El motivo del cambio, según lo que explica <a href="http://www.anandtech.com/show/2888" target="_blank">este excelente post de AnandTech</a>, se debe a que existen <strong>3 factores esenciales que deben compensarse para buscar capacidades de almacenamiento cada vez mayores</strong> en el mismo tamaño de disco (que por lo general es de 3,5 pulgadas):</p>
<ol>
<li><a href="http://en.wikipedia.org/wiki/Memory_storage_density" target="_blank">Densidad de área</a>: Cuántos bits se pueden guardar en un área determinada (Bits/Pulgada cuadrada). Hasta ahora, con la <a href="http://en.wikipedia.org/wiki/Perpendicular_recording" target="_blank">Grabación Perpendicular</a>, estamos en el orden de unos 300/500 Gigabits por pulgada cuadrada (<a href="http://arstechnica.com/hardware/news/2006/09/7765.ars" target="_blank">1</a>, <a href="http://arstechnica.com/science/news/2010/05/new-hard-drive-write-method-packs-in-one-terabyte-per-inch.ars" target="_blank">2</a>).</li>
<li><a href="http://en.wikipedia.org/wiki/Signal-to-noise_ratio" target="_blank">Relación Señal/Ruido</a>: Al leer de los platos del disco, pueden ocurrir fallos, ya que el almacenamiento magnético en definitiva es analógico; y la señal, para ser convertida desde/hacia binario, debe ser procesada. Cuanto mejor sea la relación de la señal con respecto al ruido en el momento de leer o escribir en los platos, más confiable es la operación.</li>
<li>El uso del <a href="http://en.wikipedia.org/wiki/Forward_error_correction" target="_blank">Código de Corrección de Errores &#8211; ECC</a>: Cada sector del disco incluye un área reservada para almacenar el ECC, imprescindible para recuperarse ante cualquier error de lectura/escritura.</li>
</ol>
<p>A medida que la Densidad del Area se incrementa, los sectores (siempre de 512 Bytes) lógicamente se reducen en el área que ocupan físicamente. Esto hace que se incremente el Ruido con respecto a la Señal porque las señales son más débiles y hay más interferencia de los datos adyacentes; por lo tanto el valor de SNR disminuye, y a su vez, la probabilidad de errores de lectura aumenta. Entonces, es necesario mejorar la capacidad del ECC para detectar y corregir errores, generalmente agregándole más bits. Esto requiere de más espacio físico reservado para un sector (siempre de 512 Bytes), y aquí volvemos a empezar.</p>
<p>Lo que sucede es que aquí está el punto; se está llegando a un límite donde no se puede seguir con sectores de 512 Bytes y aumentar el tamaño total del disco, ya que todo este nuevo espacio obtenido con una mayor densidad termina no siendo utilizable, sino que será mayormente para el ECC (es decir, redundancia para contemplar posibles errores).</p>
<p>La solución al problema es que, para almacenar más información globalmente, hay que incrementar la eficiencia del ECC. Y esto se logra haciendo que éste abarque más datos que sólo 512 Bytes; <strong>el ECC es mucho más eficiente (ocupa menos espacio en comparación) si su código de corrección abarca más datos</strong>, digamos, 4096 Bytes.</p>
<p>Por ejemplo, para detectar y corregir corregir 4096 Bytes divididos en 8 sectores de 512 Bytes (de la vieja forma), necesitamos &#8220;gastar&#8221; 320 Bytes de ECC (ya que tenemos 40 Bytes por cada ECC de 512 Bytes), mientras que si usamos 1 sector de 4096 Bytes sólo vamos a usar 100 Bytes de ECC. Como se puede ver, uno se ahorra 220 Bytes de <em>overhead </em>por cada 4KB que tiene el disco para guardar cosas; en 1500 GB (= 1.500.000.000 KB / 4 = 375.000.000 sectores de 4 KB * 0,22 KB) son 82,5 GB más de espacio disponible para almacenar datos de usuario y no ECC (un 5,5% más). Esto y sin contar el espacio &#8220;desperdiciado&#8221; para los <em>gaps</em> entre sectores y el flag de sincronización/inicio de sector (para 4 KB, antes eran 8 y ahora es sólo 1). Además, estos 100 Bytes de ECC mejoran en un 50% la capacidad de detectar errores en &#8220;ráfaga&#8221; comparado con el anterior, es decir, <strong>el nuevo es un mejor y más eficiente ECC</strong>.</p>
<p>Por todo esto, para tamaños tan grandes de disco, usar sectores de 4KB nos permite aprovechar de manera más eficiente la mayor densidad del área que disponemos. <strong>¿Y por qué 4 KB? No es un número al azar</strong>; coincide con el tamaño de las páginas de memoria en la arquitectura x86 y con el tamaño de <a href="http://en.wikipedia.org/wiki/Data_cluster" target="_blank">cluster</a> por defecto de la mayoría de los sistemas de archivos que pululan por ahí, con lo cual la velocidad de transferencia de páginas desde/hacia el disco no se ve afectada, y la fragmentación interna de los archivos almacenados es la misma que con sectores de 512 Bytes.</p>
<p>Quizás con el gráfico se entienda un poco más; allí se ve cómo ocupan más lugar los 8 sectores de 512 Bytes puestos a la par del sector de 4 KB:</p>
<p><a href="http://www.anandtech.com/show/2888"><img class="aligncenter size-full wp-image-750" title="Comparación sectores de 512 Bytes vs 4 KBytes" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/4kview.png" alt="" width="570" height="146" /></a></p>
<p>Nuevamente (espero comentarios y corrijo en todo caso), toda esta info está bien explicada en el <a href="http://www.anandtech.com/show/2888" target="_blank">artículo de AnandTech</a>, en <a href="http://arstechnica.com/microsoft/news/2010/03/why-new-hard-disks-might-not-be-much-fun-for-xp-users.ars" target="_blank">este artículo de Ars Technica</a>, en el <a href="http://www.wdc.com/wdproducts/library/?id=216&amp;type=87" target="_blank">Paper de WD</a> y en <a href="http://www.ibm.com/developerworks/linux/library/l-4kb-sector-disks/index.html?ca=dgr-lnxw074KB-Disksdth-LX" target="_blank">este artículo de IBM</a>.</p>
<p>Bien, &#8220;¿Y qué gano con sectores más grandes? ¿en qué me afecta?&#8221;, es lo primero que uno se pregunta. Claramente, y por lo explicado recientemente,<strong> se gana en confiabilidad y capacidad de almacenamiento hoy y a futuro</strong>. <strong>¿Cuáles son las contras? básicamente, el proceso de migración</strong>, que como ya se dijo, deben afrontarse desde varias capas de software, desde el BIOS, pasando por el Sistema Operativo y llegando a las herramientas de defragmentación, clonado y administración de discos.</p>
<h2>¿Y qué problema hay con Linux? Particiones desalineadas.</h2>
<p>Teniendo en mente esto, esta serie de discos de WD<strong> emula ser un disco con sectores &#8220;lógicos&#8221;de 512 bytes, pero en realidad trabaja internamente con sectores &#8220;físicos&#8221; de 4 KB</strong>. De esta manera, los sectores de 512 bytes lógicos se ven así, dentro de uno de 4 KB:</p>
<p><a href="http://www.anandtech.com/show/2888"><img class="aligncenter size-full wp-image-764" title="Sectores de 512Bytes en uno de 4KB" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/512B.png" alt="" width="586" height="64" /></a>Recordemos, la mínima unidad &#8220;direccionable&#8221; real del disco son 4 KB (un sector), y el tamaño de cluster por defecto (la mínima unidad &#8220;direccionable&#8221; por el sistema de archivos) son 4 KB; esto quiere decir en definitiva que el disco, cada vez que lee y escribe lo hace en unidades de 4 KB. Luego le agregamos la capa de emulación, para hacerlo compatible con los SOs que tenemos ahora. Bien, supongamos que vamos a crear una sola partición en el disco. <strong>¿Qué pasa si esta partición, donde vamos a guardar los datos, comienza en el sector 1 (o cualquier sector no múltiplo de 8 ) del disco en vez del sector 0?</strong> Va a pasar esto:</p>
<p><a href="http://www.anandtech.com/show/2888"><img class="aligncenter size-full wp-image-765" title="Cluster desalineado" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/sector.png" alt="" width="586" height="90" /></a></p>
<p>Lo que sucede es que el primer cluster empieza y termina en dos sectores físicos; está &#8220;desalineado&#8221; con respecto a ellos. En realidad, todos los clusters de la partición estarán de esta forma, comenzando y finalizando a &#8220;destiempo&#8221; respecto de los bloques físicos. El problema que esto conlleva es que si el SO va a escribir algo en el disco (donde el &#8220;algo&#8221; es como mínimo generalmente un cluster de 4 KB), supongamos el cluster resaltado en azul, esto se transforma físicamente en:</p>
<ol>
<li>Leer los 4 KB del sector físico 0.</li>
<li>Modificar los 7 sectores lógicos afectados por esta operación.</li>
<li>Grabar los 4 KB del sector físico 0.</li>
<li>Leer los 4 KB del sector físico 1.</li>
<li>Modificar el 8vo sector lógico.</li>
<li>Grabar los 4 KB del sector físico 1.</li>
</ol>
<p>Esto es, 2 operaciones de Leer-Modificar-Grabar (<a href="http://en.wikipedia.org/wiki/Read-modify-write" target="_blank">RMW</a>) atómicas, una para cada sector físico, que involucra una vuelta (<em>spin</em>) de disco por cada lectura/escritura de la lista enumerada. Es decir, <strong>que una partición comience en un sector lógico de 512 Bytes no múltiplo de 8 hace excesivamente lento el acceso al disco porque las operaciones llevan mucho, mucho más tiempo que antes</strong>.</p>
<p>Y la cuestión reside aquí; si bien Linux a esta altura ya está preparado para manejar discos con sectores de 4 KB, <strong>el </strong><strong>problema es que el disco &#8220;le dice&#8221; a Linux que tiene sectores físicos de 512 bytes por la emulación, </strong><strong><a href="http://thread.gmane.org/gmane.linux.utilities.util-linux-ng/2926" target="_blank">cuando internamente trabaja con 4 KB</a></strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">marcelo@marcelo:~$ sudo hdparm -I /dev/sdb | grep Sector
	Logical/Physical Sector size:           512 bytes</pre></div></div>

<p>¿Y cuál es la consecuencia? La posibilidad de no tener los sectores alineados. Fdisk y cualquier software particionador de discos de Linux comienza la primer partición en el sector 63 de aquellos discos que reconoce como de sectores de 512 Bytes<a href="#nota2">**</a>. Esto hace que el disco funcione muy lento, como se describía en <a href="http://community.wdc.com/t5/Desktop/Problem-with-WD-Advanced-Format-drive-in-LINUX-WD15EARS/td-p/6395/">el foro de WD</a> que cité al comienzo.</p>
<h2>Cómo particionar estos discos en general y en Linux en particular</h2>
<p>Bueno, ¿cómo se hace para crear particiones de manera alineada? Es relativamente fácil. Según <a href="http://thunk.org/tytso/blog/2009/02/20/aligning-filesystems-to-an-ssds-erase-block-size/" target="_blank">Ted Ts&#8217;o</a>, donde explica que hay un problema parecido con los nuevos discos <a href="http://en.wikipedia.org/wiki/Solid_state_storage" target="_blank">SSD</a>, hay que ejecutar <a href="http://tldp.org/HOWTO/Partition/fdisk_partitioning.html" target="_blank">fdisk</a> con los parámetros &#8220;-H 224 -S 56 /dev/sdX&#8221;, siendo /dev/sdX el disco en cuestión; esto hace que todas las particiones se creen en la sesión interactiva de fdisk en sectores múltiplos de 8. Otra opción es usar <a href="http://www.gnu.org/software/parted/index.shtml" target="_blank">GNU Parted</a> con los parámetros &#8220;unit s&#8221;, y de esta manera deja a uno configurar el primer sector de cada partición (más info <a href="http://www.gnu.org/software/parted/manual/html_node/Running-Parted.html#Running-Parted" target="_blank">acá</a>).</p>
<p>En mi caso necesitaba crear 4 particiones. Este es un ejemplo de particiones bien alineadas, el último comando es para mostrar el tamaño de cada partición nada más:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">marcelo@marcelo:~$ sudo parted /dev/sdb unit s print
Modelo: ATA WDC WD15EARS-00S (scsi)
Disco /dev/sdb: 2930277168s
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. msdos
&nbsp;
Numero  Inicio       Fin          Tamaño       Tipo     Sistema de ficheros  Banderas
 1      56s          41959679s    41959624s    primary  ext4
 2      41959680s    46161919s    4202240s     primary
 3      46161920s    1673570303s  1627408384s  primary  ext4
 4      1673570304s  2930265855s  1256695552s  primary                       raid
&nbsp;
marcelo@marcelo:~$ sudo fdisk -lu /dev/sdb
&nbsp;
Disco /dev/sdb: 1500.3 GB, 1500301910016 bytes
224 cabezas, 56 sectores/pista, 233599 cilindros, 2930277168 sectores en total
Unidades = sectores de 1 * 512 = 512 bytes
Tamaño de sector (lógico / físico): 512 bytes / 512 bytes
Tamaño E/S (mínimo/óptimo): 512 bytes / 512 bytes
Identificador de disco: 0x00094da1
&nbsp;
Dispositivo Inicio    Comienzo      Fin      Bloques  Id  Sistema
/dev/sdb1   *          56    41959679    20979812   83  Linux
/dev/sdb2        41959680    46161919     2101120   82  Linux swap / Solaris
/dev/sdb3        46161920  1673570303   813704192   83  Linux
/dev/sdb4      1673570304  2930265855   628347776   fd  Linux raid autodetect
&nbsp;
marcelo@marcelo:~$ sudo parted /dev/sdb print
Modelo: ATA WDC WD15EARS-00S (scsi)
Disco /dev/sdb: 1500GB
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. msdos
&nbsp;
Numero  Inicio  Fin     Tamaño  Tipo     Sistema de ficheros  Banderas
 1      28,7kB  21,5GB  21,5GB  primary  ext4
 2      21,5GB  23,6GB  2152MB  primary
 3      23,6GB  857GB   833GB   primary  ext4
 4      857GB   1500GB  643GB   primary                       raid</pre></div></div>

<p>Nuevamente: Lo más importante para que los clusters estén alineados con los sectores físicos del disco es que cada partición debe comenzar en un sector múltiplo de 8, como el 56, ﻿41959680, 46161920 y 1673570304 de este caso.</p>
<h2>Conclusión</h2>
<p>Bueno, fue un artículo muy largo, donde me pareció que servía explayarse en el porqué de los sectores más grandes y qué problemas trae.  Tuve la grata oportunidad de intercambiar algunos mails al respecto con <a href="http://olo.org.pl/dr/cv_eng" target="_blank">Aleksander Adamowski</a>, la persona que en la lista de <a href="http://userweb.kernel.org/~kzak/util-linux-ng/" target="_blank">util-linux-ng</a> &#8220;<a href="http://thread.gmane.org/gmane.linux.utilities.util-linux-ng/2926" target="_blank">descubrió</a>&#8221; el inconveniente de la lentitud con esta serie de discos WD a base de un lote de pruebas disponible <a href="http://olo.org.pl/files/hw/postmark-automated/" target="_blank">aquí</a>.</p>
<p>Aleksander me recomendó, en resumidas cuentas, al trabajar con discos &gt; 1 TB &#8220;sospechosos&#8221; de tener sectores de 4 KB:</p>
<ul>
<li>&#8220;Las unidades de medida son críticas. Asegúrate que estás realmente operando a nivel de sectores<a href="#nota3">***</a></li>
<li>Después , hacer un test de performance es buena idea.</li>
<li>Para esto, primero trata de crear una partición desalineada, crea un sistema de archivos, y ejecuta el benchmark de <a href="http://www.shub-internet.org/brad/FreeBSD/postmark.html" target="_blank">postmark</a> usando el archivo de configuración que publiqué (<a href="http://olo.org.pl/files/hw/postmark-automated/postmark-quick.conf" target="_blank">http://olo.org.pl/files/hw/postmark-automated/postmark-quick.conf</a> &#8211; por supuesto, modifica la opción &#8220;location&#8221; en ese archivo acorde al disco a comprobar.</li>
<li>Luego, borra todas las particiones y haz lo mismo en una partición alineada. Los resultados deben ser <strong>mucho</strong> mejores en cuanto al rendimiento. Si no lo son, el disco probablemente tiene sectores físicos de 512 Bytes.&#8221;</li>
</ul>
<p>En resumen, hay que estar atentos. Sería bueno que los futuros discos que salgan con sectores de 4 KB informaran al SO qué estructura real tienen, y eliminar el &#8220;modo compatibilidad&#8221; de una vez por todas.</p>
<p>Espero que les sirva.<br />
Saludos</p>
<p><a name="nota1"></a>* En tiempos donde la capacidad de los discos era muy pequeña comparada con los de ahora, el tamaño de un cluster del sistema de archivos era igual al de un sector.</p>
<p><a name="nota2"></a>** La utilización del sector 63 corresponde a que generalmente (y por herencia histórica del <a href="http://en.wikipedia.org/wiki/Cylinder-head-sector" target="_blank">modelo de direccionamiento CHS</a>) es el primer sector del track número 1. El track 0 siempre se utilizó para el <a href="http://en.wikipedia.org/wiki/Master_boot_record" target="_blank">MBR / Master Boot Record</a>.</p>
<p><a name="nota3"></a>*** Esto porque por defecto las herramientas de particionamiento Linux no trabajan con sectores; fdisk trabaja con cilindros por ejemplo.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/06/discos-rigidos-con-sectores-de-4kb-en-linux/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>PyDay Rafaela 2010 – Introducción a wxPython</title>
		<link>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pyday-rafaela-2010-introduccion-a-wxpython</link>
		<comments>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/#comments</comments>
		<pubDate>Mon, 10 May 2010 17:32:48 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=687</guid>
		<description><![CDATA[Para no ser menos que Juanjo y Fisa, ¡qué bueno estuvo el PyDay Rafaela 2010! Muchos (muchos) asistentes, muy buena onda, y una chorizeada + fernet a la noche inolvidables&#8230; En la sección de Charlas del blog están los slides de mi &#8220;Introducción a wxPython&#8221;, más los ejemplos de rigor. También hice propaganda de Ubuntu [...]]]></description>
			<content:encoded><![CDATA[<p>Para no ser menos que <a href="http://www.juanjoconti.com.ar/2010/05/09/charla-entendiendo-decoradores-en-python/" target="_blank">Juanjo</a> y <a href="http://fisadev.blogspot.com/2010/05/pyday-rafaela-2010_09.html" target="_blank">Fisa</a>, ¡qué bueno estuvo el <a href="www.pyday.com.ar/rafaela2010/" target="_blank">PyDay Rafaela 2010</a>!</p>
<p>Muchos (muchos) asistentes, muy buena onda, y una chorizeada + fernet a la noche inolvidables&#8230; En la sección de <a href="http://blog.marcelofernandez.info/charlas/">Charlas</a> del blog están los <a href="http://marcelofernandez.info/charlas/Introduccion%20a%20wxPython.pdf">slides</a> de mi &#8220;Introducción a wxPython&#8221;, más los <a href="http://marcelofernandez.info/charlas/Introduccion%20a%20wxPython.zip">ejemplos</a> de rigor. También <a href="http://marcelofernandez.info/charlas/Ubuntu Lightning Talk.pdf">hice propaganda</a> de Ubuntu en las Lightning Talks. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </p>
<p>Acá hay un par de fotos&#8230; con los días van a ir apareciendo más cosas en el sito del evento&#8230; incluso los videos de las charlas. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<a href='http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/attachment/08052010022/' title='PyDay Rafaela 2010'><img width="150" height="150" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/05/08052010022-150x150.jpg" class="attachment-thumbnail" alt="PyDay Rafaela 2010" title="PyDay Rafaela 2010" /></a>
<a href='http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/attachment/023/' title='PyDay Rafaela 2010 - Grupo completo'><img width="150" height="150" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/05/023-150x150.jpg" class="attachment-thumbnail" alt="PyDay Rafaela 2010 - Grupo completo" title="PyDay Rafaela 2010 - Grupo completo" /></a>

<p><strong>Actualización</strong>: <a href="http://pydayrafaela.blip.tv/" target="_blank">Acá</a> están los videos de las charlas.</p>
<p>Gracias a los chicos de PyRafaela por la organización, dedicación y aguante&#8230;. ¡espero que se repita!</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Renderizando PDFs en Python con Poppler II</title>
		<link>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=renderizando-pdfs-en-python-con-poppler-ii</link>
		<comments>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 18:04:29 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=663</guid>
		<description><![CDATA[Hace unos días me llegó un mail de alguien preguntándome cómo, a partir de la parte I de este artículo, hacer un sencillo visor de PDFs con wxPython. Me encontré con algunas dificultades, principalmente que el ScrolledWindow de wxPython no permite actualizarse dinámicamente, o automáticamente según el contenido (esto sí es bastante sencillo en GTK); [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días me llegó un mail de alguien preguntándome cómo, a partir de la <a href="http://blog.marcelofernandez.info/2009/05/renderizando-pdfs-en-python-con-poppler/" target="_self">parte I de este artículo</a>, hacer un sencillo visor de PDFs con <a href="http://www.wxpython.org" target="_blank">wxPython</a>. Me encontré con algunas dificultades, principalmente que el <a href="www.wxpython.org/docs/api/wx.ScrolledWindow-class.html" target="_blank">ScrolledWindow</a> de wxPython no permite actualizarse dinámicamente, o automáticamente según el contenido (esto <a href="http://www.pygtk.org/docs/pygtk/class-gtkadjustment.html" target="_blank">sí es bastante sencillo en GTK</a>); con lo cual se complicaba hacer zoom, modificar el tamaño de la ventana y adaptar los scrollbars, etc.</p>
<p>Sin embargo, con alguna vuelta de más pude armar un ejemplo, que paso a dejar <a href="http://code.activestate.com/recipes/577195-wxpython-pdf-viewer-using-poppler/" target="_blank">acá</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># coding: utf-8</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot; 
    wxPDFViewer - Simple PDF Viewer using Python-Poppler and wxPython 
    Marcelo Fidel Fernandez - MIT License
    http://www.marcelofernandez.info - marcelo.fidel.fernandez@gmail.com
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">import</span> wx.<span style="color: black;">lib</span>.<span style="color: black;">wxcairo</span> <span style="color: #ff7700;font-weight:bold;">as</span> wxcairo
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> poppler
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> PDFWindow<span style="color: black;">&#40;</span>wx.<span style="color: black;">ScrolledWindow</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; This example class implements a PDF Viewer Window, handling Zoom and Scrolling &quot;&quot;&quot;</span>
&nbsp;
    MAX_SCALE = <span style="color: #ff4500;">2</span>
    MIN_SCALE = <span style="color: #ff4500;">1</span>
    SCROLLBAR_UNITS = <span style="color: #ff4500;">20</span>  <span style="color: #808080; font-style: italic;"># pixels per scrollbar unit</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">ScrolledWindow</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent, wx.<span style="color: black;">ID_ANY</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Wrap a panel inside</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span> = wx.<span style="color: black;">Panel</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Initialize variables</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> = <span style="color: #ff4500;">0</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> = <span style="color: #ff4500;">1</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">document</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">width</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">height</span> = <span style="color: #008000;">None</span>
        <span style="color: #808080; font-style: italic;"># Connect panel events</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_PAINT</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnPaint</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_KEY_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnKeyDown</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_LEFT_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnLeftDown</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_RIGHT_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnRightDown</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> LoadDocument<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">file</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">document</span> = poppler.<span style="color: black;">document_new_from_file</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;file://&quot;</span> + <span style="color: #008000;">file</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_n_pages</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_page</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">n_page</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">width</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span> = <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span>.<span style="color: black;">get_size</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
        <span style="color: #008000;">self</span>._UpdateSize<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnPaint<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        dc = wx.<span style="color: black;">PaintDC</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">panel</span><span style="color: black;">&#41;</span>
        cr = wxcairo.<span style="color: black;">ContextFromDC</span><span style="color: black;">&#40;</span>dc<span style="color: black;">&#41;</span>
        cr.<span style="color: black;">set_source_rgb</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># White background</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">1</span>:
            cr.<span style="color: black;">scale</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span>, <span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>
        cr.<span style="color: black;">rectangle</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, <span style="color: #008000;">self</span>.<span style="color: black;">width</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: black;">&#41;</span>
        cr.<span style="color: black;">fill</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span>.<span style="color: black;">render</span><span style="color: black;">&#40;</span>cr<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnLeftDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span> + <span style="color: #ff4500;">0.2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnRightDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span> - <span style="color: #ff4500;">0.2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, new_scale<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> new_scale <span style="color: #66cc66;">&gt;</span>= PDFWindow.<span style="color: black;">MIN_SCALE</span> <span style="color: #ff7700;font-weight:bold;">and</span> new_scale <span style="color: #66cc66;">&lt;</span>= PDFWindow.<span style="color: black;">MAX_SCALE</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> = new_scale
            <span style="color: #808080; font-style: italic;"># Obtain the current scroll position</span>
            prev_position = <span style="color: #008000;">self</span>.<span style="color: black;">GetViewStart</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Scroll to the beginning because I'm going to redraw all the panel</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Scroll</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Redraw (calls OnPaint and such)</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Refresh</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Update panel Size and scrollbar config</span>
            <span style="color: #008000;">self</span>._UpdateSize<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># Get to the previous scroll position</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Scroll</span><span style="color: black;">&#40;</span>prev_position<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, prev_position<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> 
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _UpdateSize<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        u = PDFWindow.<span style="color: black;">SCROLLBAR_UNITS</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">SetSize</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">width</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetScrollbars</span><span style="color: black;">&#40;</span>u, u, <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">width</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>/u, <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>/u<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnKeyDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        update = <span style="color: #008000;">True</span>
        <span style="color: #808080; font-style: italic;"># More keycodes in http://docs.wxwidgets.org/stable/wx_keycodes.html#keycodes</span>
        keycode = event.<span style="color: black;">GetKeyCode</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
        <span style="color: #ff7700;font-weight:bold;">if</span> keycode <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span>wx.<span style="color: black;">WXK_PAGEDOWN</span>, wx.<span style="color: black;">WXK_SPACE</span><span style="color: black;">&#41;</span>:
            next_page = <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> + <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> keycode == wx.<span style="color: black;">WXK_PAGEUP</span>:
            next_page = <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> - <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            update = <span style="color: #008000;">False</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> update <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#40;</span>next_page <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#40;</span>next_page <span style="color: #66cc66;">&lt;</span> <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span><span style="color: black;">&#41;</span>:
                <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> = next_page
                <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_page</span><span style="color: black;">&#40;</span>next_page<span style="color: black;">&#41;</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">Refresh</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MyFrame<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span>, -<span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;wxPdf Viewer&quot;</span>, size=<span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>,<span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span> = PDFWindow<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span>.<span style="color: black;">LoadDocument</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span>.<span style="color: black;">SetFocus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># To capture keyboard events</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__==<span style="color: #483d8b;">&quot;__main__&quot;</span>:
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    f = MyFrame<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    f.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si bien tengo entendido que el scroll no es &#8220;óptimo&#8221;, ya que en cada OnPaint() se redibuja todo el PDF, anda bastante bien en mi instalación y no parece ser un problema. Lógicamente sí se puede redibujar un área en particular con Cairo (sería la que queda &#8220;invalidada&#8221; por el scroll), pero wxPython me explotó al intentar algunas cosas por un lado, y me parece que en realidad no sé hacerlo bien por el otro (si alguien puede tirar una soga en esto en particular, bienvenido sea).</p>
<p>Me entretuve mucho haciendo esto, y espero que a alguien le sea de utilidad; y aunque todavía Python-Poppler no está disponible para Windows en forma binaria (pero puede ser compilado, <a href="https://bugs.launchpad.net/poppler-python/+bug/499592" target="_blank">bug acá</a>), sí se puede usar en cualquier Linux, OSX, etc. Y nuevamente, hay una <a href="http://bazaar.launchpad.net/~poppler-python/poppler-python/trunk/annotate/head:/demo/demo-poppler.py">demo</a> para hacer esto mismo con PyGTK, y la <a href="http://cgit.freedesktop.org/poppler/poppler/tree/glib/demo" target="_blank">demo de Poppler en C</a> es mucho más completa, además de fácil de leer y traducir a Python.</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reemplazando texto con expresiones regulares en Python</title>
		<link>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=reemplazando-texto-con-expresiones-regulares-en-python</link>
		<comments>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 18:01:11 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=601</guid>
		<description><![CDATA[Hay veces en que uno necesita automatizar tareas, como reemplazar cierto texto por otro bajo ciertas condiciones, y el viejo &#8220;%s/cosa/otra/g&#8221; del vim nos queda corto. En mi caso en particular, estaba metiendo algunas pequeñas características en PyFpdf, y vi que había algunos archivos .py llenos de llamadas a la función chr(). Claro, PyFpdf es [...]]]></description>
			<content:encoded><![CDATA[<p>Hay veces en que uno necesita automatizar tareas, como reemplazar cierto texto por otro bajo ciertas condiciones, y el viejo &#8220;%s/cosa/otra/g&#8221; <a href="http://www.linux.com/learn/tutorials/8255-vim-tips-the-basics-of-search-and-replace" target="_blank">del vim</a> nos queda corto. En mi caso en particular, estaba metiendo algunas pequeñas características en <a href="http://www.sistemasagiles.com.ar/trac/wiki/PyFpdf" target="_blank">PyFpdf</a>, y vi que había <a href="http://www.sistemasagiles.com.ar/trac/browser/pyfpdf/font/times.py?rev=103" target="_blank">algunos archivos .py</a> llenos de llamadas a la función <a href="http://docs.python.org/library/functions.html#chr" target="_blank">chr()</a>.</p>
<p>Claro, PyFpdf es un port más o menos &#8220;haragán&#8221; (<em>lazy</em>) de <a href="http://www.fpdf.org/" target="_blank">Fpdf para PHP</a>, y el autor original evidentemente encontró más sencillo definir algunas fuentes (en binario) haciendo sucesivas llamadas a la función chr(), como  esta:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">fpdf_charwidths<span style="color: black;">&#91;</span><span style="color: #483d8b;">'times'</span><span style="color: black;">&#93;</span>=<span style="color: black;">&#123;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>,<span style="color: black;">&#125;</span> <span style="color: #808080; font-style: italic;"># Sigue...</span></pre></div></div>

<p>Enseguida pensé en mejorarlo, reemplazando esas sucesivas llamadas a chr() por la misma función pero ya evaluada y en forma de byte string; por ejemplo, la idea era convertir lo anterior en:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">fpdf_charwidths<span style="color: black;">&#91;</span><span style="color: #483d8b;">'times'</span><span style="color: black;">&#93;</span>=<span style="color: black;">&#123;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>01'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>02'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>03'</span>:<span style="color: #ff4500;">250</span>,<span style="color: black;">&#125;</span> <span style="color: #808080; font-style: italic;"># Sigue...</span></pre></div></div>

<p>De esa manera, los archivos .py se simplificarían (se harían más legibles), no sufrirían modificaciones en su comportamiento y hasta serían más veloces en su interpretación y ejecución.</p>
<p>Primero se me ocurrió primero hacer algo más &#8220;a mano&#8221;, pero en cuanto se me complicó un poquito enseguida pensé que la mejor herramienta era usar <a href="http://es.wikipedia.org/wiki/Expresiones_regulares" target="_blank">expresiones regulares</a> para el matching del patrón &#8220;chr(x)&#8221; y, por consiguiente, el <a href="http://docs.python.org/library/re.html" target="_blank">módulo re</a> de la librería estándar de Python.</p>
<p>Leyendo <a href="http://www.amk.ca/python/howto/regex/" target="_blank">esta excelente página</a> y la documentación del módulo en cuestión, armé un script, y me quedó así:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># coding:utf-8</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># This script tries to identify all chr(XX) constant calls in python scripts</span>
<span style="color: #808080; font-style: italic;"># and replace them with '\xXX' strings.</span>
<span style="color: #808080; font-style: italic;"># Author: Marcelo Fernández - License: MIT</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> chrrepl<span style="color: black;">&#40;</span>match<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># See http://www.amk.ca/python/howto/regex/regex.html</span>
    <span style="color: #808080; font-style: italic;"># Use the captured group to get the hex string value.</span>
    char_number = match.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>char_number<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">3</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Usage: python chr_cleaner.py infile.py outfile.py'</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
    infile = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    outfile = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># Open file for reading</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        fin = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>infile, <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>
        fout = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>outfile, <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IOError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Error when reading %s or trying to write %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>infile, outfile<span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
    intext = fin.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    pattern = <span style="color: #483d8b;">'chr<span style="color: #000099; font-weight: bold;">\\</span>((<span style="color: #000099; font-weight: bold;">\\</span>d+)<span style="color: #000099; font-weight: bold;">\\</span>)'</span> <span style="color: #808080; font-style: italic;"># Group the chr() function parameter to capture it</span>
    p = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>pattern<span style="color: black;">&#41;</span>
    outtext = p.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>chrrepl, intext<span style="color: black;">&#41;</span>
    fout.<span style="color: black;">write</span><span style="color: black;">&#40;</span>outtext<span style="color: black;">&#41;</span>
    fout.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    fin.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    fout.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si bien creo que el <em>snippet</em> es bastante legible, lo interesante es que con el módulo re se puede:</p>
<ul>
<li><strong>Identificar un patrón en un texto</strong>: En este caso el patrón sería &#8220;chr(\d)&#8221; (\d porque busco un número allí).</li>
<li><strong>Marcar grupos en ese patrón utilizarlos luego</strong>; como sé que voy a utilizar el número en cuestión para convertirlo a su byte string, lo defino dentro de un grupo. El patrón queda entonces &#8220;chr((\d))&#8221;. También es posible usar <em>named groups</em>, identificables por nombre en vez de por posición, pero eso lo dejo de tarea al lector <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </li>
<li><strong>Reemplazar todo el texto que coincide con ese patrón, y en cada reemplazo, llamar a una función que especifique &#8220;lo que hay que poner&#8221; allí, devolviendo un string</strong>. Esta es la frutilla del postre&#8230; <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
Si bien puedo usar p.sub() para reemplazar lo que busco por un texto constante, también puedo hacer que en cada ocurrencia del patrón una función cualquiera sea llamada, y  se le pase la instancia de <a href="http://docs.python.org/library/re.html#re.MatchObject" target="_blank">MatchObject</a> para que decidamos qué hacer con lo encontrado y devolver un string. Esto hace la función chrrepl() del snippet. Allí tomo el primer grupo (el grupo 0 es el string completo, el 1 es el primer grupo definido posicionalmente, y así sucesivamente), lo convierto a entero, ejecuto la función chr() y devuelvo su representación en byte string.</li>
</ul>
<p>En fin, después de experimentar un buen rato, esto funcionó y <a href="http://www.sistemasagiles.com.ar/trac/changeset/104/pyfpdf/" target="_blank">acá se puede ver</a> el diff del commit correspondiente para que se aprecie un poco mejor&#8230;</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo remover el módulo USB 2.0 en Ubuntu 9.10+</title>
		<link>http://blog.marcelofernandez.info/2010/03/como-remover-el-modulo-usb-2-0-en-ubuntu-9-10/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=como-remover-el-modulo-usb-2-0-en-ubuntu-9-10</link>
		<comments>http://blog.marcelofernandez.info/2010/03/como-remover-el-modulo-usb-2-0-en-ubuntu-9-10/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 18:14:13 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=553</guid>
		<description><![CDATA[Este post va a intentar ser breve y me parece que es bastante técnico, pero puede serle útil a más de uno. Resulta que yo tengo una Impresora Multifunción Samsung SCX-4200, que tiene unos drivers (cerrados) para Linux [1]. Estos drivers sirven para imprimir y escanear, y si bien hoy en día Ubuntu se las [...]]]></description>
			<content:encoded><![CDATA[<p>Este post va a intentar ser breve y me parece que es bastante técnico, pero puede serle útil a más de uno.</p>
<p><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/03/SCX4200.jpg"><img class="alignright size-medium wp-image-583" title="Samsung SCX4200" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/03/SCX4200-300x236.jpg" alt="" width="300" height="236" /></a>Resulta que yo tengo una Impresora Multifunción <a href="http://www.samsung.com/ar/support/download/supportDown.do?group=&amp;group_cd=&amp;type=impresoras&amp;type_cd=06010000&amp;subtype=multifunci%C3%B3nblancoynegro&amp;subtype_cd=06010300&amp;model_nm=SCX-4200&amp;dType=D&amp;mType=&amp;model_cd=&amp;menu=&amp;prd_ia_cd=06010300&amp;disp_nm=SCX-4200&amp;language=" target="_blank">Samsung SCX-4200</a>, que tiene unos drivers (cerrados) para Linux [1]. Estos drivers sirven para imprimir y escanear, y si bien hoy en día Ubuntu se las arregla bárbaro para imprimir con los drivers libres de <a href="http://splix.ap2c.org/" target="_blank">SpliX</a> (¡instalación y configuración automágica!), queda pendiente aún el tema del escaneo.</p>
<p>Por algún motivo al utilizar el scanner (vía USB) la transferencia se caía, y resultó ser que la comunicación Scanner &lt;-&gt; USB 2.0 no funciona, como <a href="http://blog.marcelofernandez.info/2007/02/samsung-scx-4200-en-ubuntu-610/" target="_blank">ya documenté en este mismo blog</a> hace unos años (con la impresión no hay problemas); y no importa la mother, chip o cosa que haya en el medio (lo probé con diferentes equipos). O es esta printer en particular (mucha mala suerte), o es algo del firmware que me tocó en gracia, o&#8230; <em>shit happens</em>. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </p>
<p>En fin, en versiones anteriores de Ubuntu anteriores a 9.10, <strong>para forzar una comunicación USB 1.1 se solucionaba con un &#8220;sudo rmmod ehci_hcd&#8221;</strong>, porque el módulo USB 2.0 (ehci_hcd) era justamente, un módulo que se cargaba dinámicamente. Pero a partir de Ubuntu 9.10 (¿o antes?) este módulo fue incluido en el kernel (estáticamente), con lo cual a priori no tenía manera sencilla de forzar una comunicación USB 1.1 con algún dispositivo (que no sea cambiar el parámetro correspondiente en el BIOS), ya que no es posible descargar un módulo estático del kernel (más info <a href="http://structio.sourceforge.net/guias/AA_Linux_colegio/kernel-y-modulos.html" target="_blank">acá</a>).</p>
<p style="text-align: left;"><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/03/800px-USB_types_2.jpg"><img class="size-medium wp-image-588 aligncenter" title="Conectores USB" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/03/800px-USB_types_2-300x139.jpg" alt="" width="300" height="139" /></a><br />
Me puse a buscar, y encontré una solución. Para simular la &#8220;descarga&#8221; el módulo es necesario posicionarse en el directorio /sys/bus/pci/drivers/ehci_hcd y pasarle al archivo &#8220;unbind&#8221; qué hub USB &#8220;unbindear&#8221; (¿&#8221;desrelacionar&#8221;?); los hubs USB se pueden ver con un lsusb -v, y los que van a aparecer en el directorio mencionado son los de &#8220;Full Speed&#8221;, o sea, los de USB 2.0 [2] .</p>
<p>Si tu PC soporta USB 2.0 (y por ende tenés este problema, je), al menos uno hay, que corresponde al Hub de la motherboard. En mi caso hay dos, pero para no andar especulando (y porque quiero que el scanner funcione sin averiguar a cuál de los dos hub está conectado en particular), &#8220;unbindeo&#8221;/&#8221;desrelaciono&#8221;/&#8221;desenlazo&#8221; (?) ambos hubs:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">marcelo<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:~$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-i</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #c20cb9; font-weight: bold;">sudo</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> password <span style="color: #000000; font-weight: bold;">for</span> marcelo:
root<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:~<span style="color: #666666; font-style: italic;"># cd /sys/bus/pci/drivers/ehci_hcd/</span>
root<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:<span style="color: #000000; font-weight: bold;">/</span>sys<span style="color: #000000; font-weight: bold;">/</span>bus<span style="color: #000000; font-weight: bold;">/</span>pci<span style="color: #000000; font-weight: bold;">/</span>drivers<span style="color: #000000; font-weight: bold;">/</span>ehci_hcd<span style="color: #666666; font-style: italic;"># ls -l</span>
total <span style="color: #000000;">0</span>
lrwxrwxrwx <span style="color: #000000;">1</span> root root    <span style="color: #000000;">0</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> 0000:00:1a.7 -<span style="color: #000000; font-weight: bold;">&gt;</span> ..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>devices<span style="color: #000000; font-weight: bold;">/</span>pci0000:00<span style="color: #000000; font-weight: bold;">/</span>0000:00:1a.7
lrwxrwxrwx <span style="color: #000000;">1</span> root root    <span style="color: #000000;">0</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> 0000:00:1d.7 -<span style="color: #000000; font-weight: bold;">&gt;</span> ..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>devices<span style="color: #000000; font-weight: bold;">/</span>pci0000:00<span style="color: #000000; font-weight: bold;">/</span>0000:00:1d.7
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> <span style="color: #7a0874; font-weight: bold;">bind</span>
lrwxrwxrwx <span style="color: #000000;">1</span> root root    <span style="color: #000000;">0</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> module -<span style="color: #000000; font-weight: bold;">&gt;</span> ..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>module<span style="color: #000000; font-weight: bold;">/</span>ehci_hcd
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> new_id
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> remove_id
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> uevent
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> unbind
root<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:<span style="color: #000000; font-weight: bold;">/</span>sys<span style="color: #000000; font-weight: bold;">/</span>bus<span style="color: #000000; font-weight: bold;">/</span>pci<span style="color: #000000; font-weight: bold;">/</span>drivers<span style="color: #000000; font-weight: bold;">/</span>ehci_hcd<span style="color: #666666; font-style: italic;"># echo -n 0000\:00\:1a.7 &gt; unbind</span>
root<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:<span style="color: #000000; font-weight: bold;">/</span>sys<span style="color: #000000; font-weight: bold;">/</span>bus<span style="color: #000000; font-weight: bold;">/</span>pci<span style="color: #000000; font-weight: bold;">/</span>drivers<span style="color: #000000; font-weight: bold;">/</span>ehci_hcd<span style="color: #666666; font-style: italic;"># echo -n 0000\:00\:1d.7 &gt; unbind</span>
root<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:<span style="color: #000000; font-weight: bold;">/</span>sys<span style="color: #000000; font-weight: bold;">/</span>bus<span style="color: #000000; font-weight: bold;">/</span>pci<span style="color: #000000; font-weight: bold;">/</span>drivers<span style="color: #000000; font-weight: bold;">/</span>ehci_hcd<span style="color: #666666; font-style: italic;"># ls -l</span>
total <span style="color: #000000;">0</span>
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> <span style="color: #7a0874; font-weight: bold;">bind</span>
lrwxrwxrwx <span style="color: #000000;">1</span> root root    <span style="color: #000000;">0</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> module -<span style="color: #000000; font-weight: bold;">&gt;</span> ..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>..<span style="color: #000000; font-weight: bold;">/</span>module<span style="color: #000000; font-weight: bold;">/</span>ehci_hcd
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> new_id
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> remove_id
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">12</span> uevent
<span style="color: #660033;">--w-------</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">19</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">21</span> unbind
root<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:<span style="color: #000000; font-weight: bold;">/</span>sys<span style="color: #000000; font-weight: bold;">/</span>bus<span style="color: #000000; font-weight: bold;">/</span>pci<span style="color: #000000; font-weight: bold;">/</span>drivers<span style="color: #000000; font-weight: bold;">/</span>ehci_hcd<span style="color: #666666; font-style: italic;">#</span></pre></div></div>

<div>Listo el pollo. Todos los dispositivos USB que estén conectados por medio de estos Hubs van a ser reconocidos y utilizados por el &#8220;fallback&#8221;, USB 1.1; en definitiva, este es manejado por el módulo linux uhci_hcd, como podemos ver con el comando dmesg:</div>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64720.180444</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ehci_hcd 0000:00:1a.7: remove, state <span style="color: #000000;">4</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64720.180464</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> usb usb1: USB disconnect, address <span style="color: #000000;">1</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64720.184731</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ehci_hcd 0000:00:1a.7: USB bus <span style="color: #000000;">1</span> deregistered
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64720.184838</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ehci_hcd 0000:00:1a.7: PCI INT C disabled
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64730.610396</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ehci_hcd 0000:00:1d.7: remove, state <span style="color: #000000;">1</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64730.610417</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> usb usb2: USB disconnect, address <span style="color: #000000;">1</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64730.610422</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> usb <span style="color: #000000;">2</span>-<span style="color: #000000;">4</span>: USB disconnect, address <span style="color: #000000;">3</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64730.684860</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ehci_hcd 0000:00:1d.7: USB bus <span style="color: #000000;">2</span> deregistered
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64730.684980</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ehci_hcd 0000:00:1d.7: PCI INT A disabled
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64731.070210</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> usb <span style="color: #000000;">6</span>-<span style="color: #000000;">2</span>: new full speed USB device using uhci_hcd and address <span style="color: #000000;">5</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64731.254158</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> usb <span style="color: #000000;">6</span>-<span style="color: #000000;">2</span>: configuration <span style="color: #666666; font-style: italic;">#1 chosen from 1 choice</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64731.259814</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> uvcvideo: Found UVC <span style="color: #000000;">1.00</span> device FO13FF-<span style="color: #000000;">50</span> PC-CAM <span style="color: #7a0874; font-weight: bold;">&#40;</span>05c8:0100<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">64731.273207</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> input: FO13FF-<span style="color: #000000;">50</span> PC-CAM <span style="color: #c20cb9; font-weight: bold;">as</span> <span style="color: #000000; font-weight: bold;">/</span>devices<span style="color: #000000; font-weight: bold;">/</span>pci0000:00<span style="color: #000000; font-weight: bold;">/</span>0000:00:1d.1<span style="color: #000000; font-weight: bold;">/</span>usb6<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">6</span>-<span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">6</span>-<span style="color: #000000;">2</span>:<span style="color: #000000;">1.0</span><span style="color: #000000; font-weight: bold;">/</span>input<span style="color: #000000; font-weight: bold;">/</span>input11
<span style="color: #7a0874; font-weight: bold;">&#91;</span>...<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></div></div>

<p>En mi caso no tenía conectada la impresora, pero sirve el ejemplo de todas maneras ver cómo la webcam es reconocida por uhci_hcd (USB 1.1). Para volver atrás, supongo que hay que hacer lo mismo pero con bind (no lo probé, sólo me parece lógico&#8230;), aunque yo reinicio la máquina para no complicarme. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </p>
<p>Esto es fácil de meter en un script, y espero que le sirva a alguien (me llevó un buen rato encontrarlo).</p>
<p>Saludos</p>
<p>Marcelo</p>
<div>[1] Por algún motivo la gente de Samsung sacó los drivers Linux de la página de la printer al momento de escribir esto (?). Ya les envié un mail al respecto, espero que contestesten y/o vuelvan a aparecer (habían sido actualizados hace un par de meses, no parecían estar sin mantener&#8230;). Si alguien los necesita, me escribe y los pongo en algún lugar accesible.</div>
<div><span style="text-decoration: underline;">Actualización</span>: Me contestaron enseguida, a las 3 horas de haberles escrito que no hay drivers Linux en su página. Según ellos, se disculpan y afirman que puede que el equipo de desarrollo esté actualizando los drivers en este mismo momento&#8230; hay que ver en unos días si aparecen.</div>
<div></div>
<div>[2] Acá hay una porción de la salida de un &#8220;lsusb -v&#8221; donde aparece uno de los 2 Root Hub USB 2.0 que tengo en mi equipo; ver que el archivo relacionado que aparece en el directorio /sys/bus/pci/drivers/ehci_hcd corresponde al descriptor &#8220;iSerial&#8221; del mismo:</div>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation <span style="color: #000000;">2.0</span> root hub
Device Descriptor:
  bLength                <span style="color: #000000;">18</span>
  bDescriptorType         <span style="color: #000000;">1</span>
  bcdUSB               <span style="color: #000000;">2.00</span>
  bDeviceClass            <span style="color: #000000;">9</span> Hub
  bDeviceSubClass         <span style="color: #000000;">0</span> Unused
  bDeviceProtocol         <span style="color: #000000;">0</span> Full speed <span style="color: #7a0874; font-weight: bold;">&#40;</span>or root<span style="color: #7a0874; font-weight: bold;">&#41;</span> hub
  bMaxPacketSize0        <span style="color: #000000;">64</span>
  idVendor           0x1d6b Linux Foundation
  idProduct          0x0002 <span style="color: #000000;">2.0</span> root hub
  bcdDevice            <span style="color: #000000;">2.06</span>
  iManufacturer           <span style="color: #000000;">3</span> Linux 2.6.31-<span style="color: #000000;">20</span>-generic ehci_hcd
  iProduct                <span style="color: #000000;">2</span> EHCI Host Controller
  iSerial                 <span style="color: #000000;">1</span> 0000:00:1d.7
  bNumConfigurations      <span style="color: #000000;">1</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>...<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/03/como-remover-el-modulo-usb-2-0-en-ubuntu-9-10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Virtio – Paravirtualización de I/O</title>
		<link>http://blog.marcelofernandez.info/2010/02/virtio-paravirtualizacion-de-io/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=virtio-paravirtualizacion-de-io</link>
		<comments>http://blog.marcelofernandez.info/2010/02/virtio-paravirtualizacion-de-io/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 19:55:25 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=538</guid>
		<description><![CDATA[Hace un rato que estoy leyendo sobre virtualización, pero no de CPU, sino de I/O (otro más acá)&#8230; muy interesante, me aclaró algunas dudas que tenía, dado que últimamente al configurar este tipo de software se me confundían las cosas Resulta que a nivel de I/O tenemos algo parecido a la virtualización al nivel de CPU: emulación, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.linux-kvm.org"><img class="size-full wp-image-539 alignright" title="kvmbanner-logo2" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/02/kvmbanner-logo2.png" alt="" width="300" height="93" /></a> Hace un rato que estoy leyendo sobre virtualización, pero no de CPU, sino de <a href="http://arstechnica.com/business/guides/2010/02/io-virtualization.ars/" target="_blank">I/O</a> (otro más <a href="http://www.ibm.com/developerworks/linux/library/l-virtio/index.html?ca=dgr-lnxw07Viriodth-LX&amp;S_TACT=105AGX59&amp;S_CMP=grlnxw07" target="_blank">acá</a>)&#8230; muy interesante, me aclaró algunas dudas que tenía, dado que últimamente al configurar este tipo de software se me confundían las cosas <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Resulta que a nivel de I/O tenemos algo parecido a la virtualización al nivel de CPU: emulación, paravirtualización y ejecución &#8220;directa&#8221;, por llamarlo de alguna manera. Sugiero leer el artículo para más detalles, pero sólo quiero agregar que recién estamos en la etapa de paravirtualización, y que (en buena hora) Intel y AMD agregaron unidades <a href="http://en.wikipedia.org/wiki/IOMMU" target="_blank">IOMMU</a> en sus últimos diseños para poder asignar dispositivos directamente a una (o más, según el caso) VM, evitando el Hypervisor y ahorrando ciclos de CPU. Pero esto parece estar verde aún.</p>
<p><a href="http://wiki.libvirt.org/page/Virtio" target="_blank">Virtio</a> vendría a ser como una serie de drivers de paravirtualización de I/O. Lo bueno es que no sabía que <a href="http://www.virtualbox.org/" target="_blank">VirtualBox</a> <a href="http://www.virtualbox.org/manual/ch06.html#nichardware" target="_blank">soportaba</a> para las interfaces de red, algo que al parecer (y de esta manera) intenta ser un estándar  (net y block devices por ahora),  ya que tiene una API de comunicación Host &lt;&#8211;&gt; Guest abierta, independiente y en paralelo a la propuesta de <a href="http://www.linux-kvm.org/page/Main_Page" target="_blank">KVM</a> como hypervisor.</p>
<p>Luego de ver un poco todo esto, me puse  a configurarlo en una VM con WinXP, le instalé <a href="http://www.linux-kvm.org/page/WindowsGuestDrivers/Download_Drivers" target="_blank">estos drivers</a> y ya estoy usando menos CPU para la parte de red en mi guest <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p style="text-align: center;"><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/02/Pantallazo-Windows-XP-Configuración.png"><img class="size-medium wp-image-540 aligncenter" title="Pantallazo-Windows XP - Configuración" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/02/Pantallazo-Windows-XP-Configuración-300x201.png" alt="" width="300" height="201" /></a></p>
<p>Acá se ve un poco la mejora a nivel de tráfico de red *real* que hay usando I/O paravirtualizado:</p>
<p><a href="http://www.linux-kvm.org/page/Using_VirtIO_NIC" target="_blank">http://www.linux-kvm.org/page/Using_VirtIO_NIC</a></p>
<p>En fin, esperemos que todo esto mejore más aún. KVM ya soporta virtio para <a href="http://www.linux-kvm.com/content/redhat-54-windows-virtio-drivers-part-2-block-drivers" target="_blank">dispositivos de almacenamiento</a>, además de<a href="http://www.linux-kvm.com/content/tip-how-setup-windows-guest-paravirtual-network-drivers" target="_blank"> los de red</a> (linkeo la instalación de los drivers de Windows porque lógicamente Linux tiene estas baterías ya incluídas, je).</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/02/virtio-paravirtualizacion-de-io/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
