Mostrando entradas con la etiqueta Debian. Mostrar todas las entradas
Mostrando entradas con la etiqueta Debian. Mostrar todas las entradas

domingo, 29 de diciembre de 2013

Instalación de Redmine en Debian 7




A la hora de gestionar proyectos existen multitud de herramientas y opciones disponibles. Algunas son gratis, otras no, unas ofrecen la posibilidad de instalarlas en tus propios servidores, otras se contratan "en la nube".
Redmine es una de las que permiten instalarlo en tus propios servidores. Se trata de un gestor de proyectos escrito con Ruby on Rails, es multiplataforma y soporta múltiples bases de datos. Además es software libre con licencia GPLv2.
Entre sus características destaca el soporte multi-proyecto, sistema de roles y permisos muy flexible y personalizable, gestión de tareas, wikis, foros, subida de archivos y documentos, notificaciones por email y por RSS,...

Llevo casi 4 años utilizando Redmine en el día a día del trabajo (además de administrándolo) y después de instalarlo varias veces de cero y actualizarlo entre versiones otras tantas por fin me he decidido a juntar todas mis notas y escribir un tutorial actualizado.

Partimos de una Debian 7 64 bits recién instalada sin nada adicional a excepción de OpenSSH. Toda la instalación se realizará con un usuario no root en su home, aunque algunos comandos requieren el uso de sudo. Aunque Redmine viene configurado por defecto para utilizar MySQL, en mi caso lo voy a instalar utilizando Postgresql.

Instalación de Postgresql 9.3

En los repos de Debian no está la última versión por lo que lo mejor es utilizar un repo oficial. En la actualidad ya se ha publicado la versión 9.3.2 y será ésta la que utilicemos.

  • Añadir el repo de Postgres
  • sudo vi /etc/apt/sources.list.d/pgdg.list
    
    # Postgresql
    deb http://apt.postgresql.org/pub/repos/apt/ wheezy-pgdg main
    
  • Añadir clave de verificación
  • wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
    
  • Actualizar los paquetes e instalar postgresql-9.3
  • sudo apt-get update
    sudo apt-get install postgresql-9.3
    
  • Damos permisos para conectarnos a las bases de datos
  • sudo vi /etc/postgresql/9.3/main/pg_hba.conf
    
    # Cambiar la siguiente línea:
    local   all             postgres                                peer
    
    # por:
    local   all             postgres                                trust
    
  • Reiniciar el servidor para que aplique los cambios:
  • sudo /etc/init.d/postgresql restart
    
  • Crear la base de datos
  • $ psql -U postgres
    psql (9.3.2)
    Type "help" for help.
    
    postgres=# CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'my-secret-password' NOINHERIT VALID UNTIL 'infinity';
    postgres=# CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;
    

    Instalación de paquetes adicionales

    Para poder compilar las gemas de ruby que instalaremos más tarde necesitamos una serie de paquetes. Algunos son los mínimos para poder compilar cualquier fuente: gcc, make,... y otros son necesarios para las gemas.
    sudo apt-get install build-essential
    
    Instalar librería necesaria para utilizar Postgresql desde una aplicación Ruby on Rails
    sudo apt-get install libpq-dev
    

    Instalación de Apache

    Para poder servir el Redmine una vez instalado vamos a utilizar apache.
    Instalar apache2 y habilitar los módulos necesarios:
    sudo apt-get install apache2 libapache2-mod-fcgid libapache2-mod-proxy-html libfcgi-dev
    
    sudo a2enmod rewrite
    sudo a2enmod proxy_http
    sudo a2enmod proxy
    

    Instalación de ImageMagick

    Para la generación de pdfs y pngs Redmine utiliza ImageMagick, por lo que si queremos utilizar esta funcionalidad deberemos instalarlo junto con las librerías necesarias.
    $ sudo apt-get install imagemagick libmagickwand-dev libmagickcore-dev
    

    Instalación de Ruby

    Ahora ya podemos instalar Ruby. Utilizaremos la versión 1.9.3.
    sudo apt-get install ruby1.9.3
    

    Instalación de Redmine

    Por fin, después de haber instalado todas las dependencias podemos empezar con la instalación de Redmine.
  • Descargar la última versión disponible. En el momento de escribir este artículo es la versión 2.4.2
  • wget http://www.redmine.org/releases/redmine-2.4.2.tar.gz
    tar zxvf redmine-2.4.2.tar.gz
    ln -s redmine-2.4.2 redmine
    cd redmine
    
    La creación del enlace simbólico no es necesaria pero es una buena práctica. Además nos sirve en el futuro para actualizar la versión sin tener que tocar la configuración del Apache.
  • Crear el archivo de configuración de la base de datos a partir del que viene de ejemplo y editarlo
  • cp config/database.yml.example config/database.yml
    vi config/database.yml
    
    production:
      adapter: postgresql
      database: redmine
      host: localhost
      username: redmine
      password: "my-secret-password"
      encoding: utf8
    
    Importante quitar mysql de los environments de develop y test porque sino luego intentará instalar las dependencias y fallará. Poner "postgresql" en todos aunque no se configure nada más. Sólo vamos a usar el environment de producción.
  • Añadir una gema que luego utilizaremos para que se instale junto con el resto.
  • echo 'gem "fcgi"' > Gemfile.local
    
  • Instalar gema de postgresql
  • sudo gem install pg
    
  • Instalar gestor de gemas
  • sudo gem install bundler
    
  • Instalar todas las dependencias de Redmine
  • sudo bundle install --without development test
    
  • Crear las tablas de la base de datos
  • RAILS_ENV=production rake db:migrate
    
  • Crear los datos iniciales (recomendado en inglés)
  • RAILS_ENV=production rake redmine:load_default_data
  • Crear directorios y dar permisos
  • mkdir -p tmp tmp/pdf public/plugin_assets
    chmod -R 755 files log tmp public/plugin_assets
    
  • Generar el session store secret
  • rake generate_secret_token
    Y listo, ahora sólo falta probar que todo funciona correctamente. Para ello, ejecutamos el servidor web embebido (no utilizar en producción).
    $ ruby script/rails server webrick -e production
    => Booting WEBrick
    => Rails 3.2.13 application starting in production on http://0.0.0.0:3000
    => Call with -d to detach
    => Ctrl-C to shutdown server
    [2013-12-28 11:05:17] INFO  WEBrick 1.3.1
    [2013-12-28 11:05:17] INFO  ruby 1.9.3 (2013-11-22) [x86_64-linux]
    [2013-12-28 11:05:17] INFO  WEBrick::HTTPServer#start: pid=25214 port=3000
    
    Nos conectamos con el navegador a http://localhost:3000 y nos logamos con admin/admin.

    Configuración de Apache

    Para servir el Redmine para poder utilizarlo en producción vamos a utilizar Apache junto con fcgi.
  • Desde el directorio redmine copiamos el archivo htaccess y de fcgi a partir de las plantillas.
  • cp public/htaccess.fcgi.example public/.htaccess
    cp public/dispatch.fcgi.example public/dispatch.fcgi
    chmod +x public/dispatch.fcgi
    
  • Editar el archivo de configuración de entornos para utilizar el de producción por defecto
  • vi config/environment.rb
    
    # Añadir la siguiente línea al principio del archivo
    ENV['RAILS_ENV'] ||= 'production'
    
  • Añadir el nuevo virtual host al apache
  • sudo vi /etc/apache2/sites-enabled/000-default
    
    <VirtualHost *:80>
        ErrorLog /var/log/apache2/redmine-error-log
        CustomLog /var/log/apache2/redmine-access-log combined
    
        ServerName redmine.my-domain.com
        ServerAdmin admin@my-domain.com
        DocumentRoot /home/ivan/redmine/public
        ProxyPreserveHost On
    
        <Directory "/home/ivan/redmine/public/">
            Options Indexes ExecCGI FollowSymLinks
            Order allow,deny
            Allow from all
            AllowOverride all
        </Directory>
    </VirtualHost>
    
  • Dar permisos de escritura al usuario de apache a algunos archivos y directorios
  • sudo chown -R www-data:www-data files log tmp public/plugin_assets
  • Reiniciar apache
  • sudo /etc/init.d/apache2 restart
    Y listo, si todo va bien deberíamos poder conectarnos a nuestro nuevo Redmine con el dominio que hayamos definido en nuestro virtual host, en este caso http://redmine.my-domain.com.

    Bola extra: Actualizar una versión antigua de Redmine

    Como he comentado al principio del artículo, llevo utilizando Redmine casi 4 años (empecé en la versión 0.9.6) y he actualizado de versión en bastantes ocasiones. El proceso de actualización es muy simple.

  • Instalar la nueva versión como hemos hecho hasta ahora y comprobar que todo funciona correctamente.
  • Parar apache y hacer una copia de seguridad de nuestra base de datos actual (espero que además hagas copias periódicas).
  • sudo /etc/init.d/apache2 stop
    pg_dump -U postgres redmine > db_redmine.sql
    
  • Después de instalar la nueva versión de redmine, en lugar de crear todas las tabla en la base de datos, lo que tenemos que hacer es ejecutar la migración de las mismas.
  • rake db:migrate RAILS_ENV=production
    
    Esto lo que hace es ejecutar todas las migraciones desde la versión que teníamos instalada hasta la versión actual para que el modelo de datos sea el adecuado.
  • Si tenemos plugins instalados, ejecutar sus migraciones.
  • rake redmine:plugins:migrate RAILS_ENV=production
  • Copiar los archivos subidos del directorio files del redmine antiguo al nuevo.
  • Limpiar cache y sesiones.
  • rake tmp:cache:clear
    rake tmp:sessions:clear
    
  • Finalmente reiniciar apache y logarnos de nuevo. Luego, en el menú Administration -> Information podemos comprobar que la migración se ha realizado correctamente y estamos con la versión adecuada:


    Para el que no esté muy seguro sobre las actualizaciones, decir que en todas las actualizaciones de estos años no he tenido ningún problema y todas han funcionado a la perfección. En esta última actualización he pasado directamente de la versión 1.4.4 a la 2.4.2. Han sido cinco versiones mayor (2.0, 2.1, 2.2, 2.3 y 2.4) y 27 versiones en total de diferencia entre ambas y cero problemas :-)
  • jueves, 2 de octubre de 2008

    Ampliando un raid 1 en linux

       Resulta que el raid 1 que monté en mi servidor de backup estaba al 96% de sus escasos 60GB. De hecho, la última vez que lancé el backup se me llenó y tuve que estar borrando archivos y arreglando el estropicio a mano.
    shian:~# df -h
    S.ficheros Tamaño Usado Disp Uso% Montado en
    /dev/md0 56G 50G 2,6G 96% /mnt/raid

       Así, me decidí por un par de discos de 320GB y el pasado fin de semana estuve haciendo el cambio. El proceso es muy sencillo y no tiene ningún truco ni paso especial que haya que realizar. Como ya he puesto varios tutoriales sobre el raid 1, lo único que voy a comentar son los pasos que seguí por si alguien necesita ampliar el suyo pero sin mucho detalle. Para información adicional os remito al artículo original del raid 1 en linux.
  • Conectar los discos y particionarlos.
    shian:~# fdisk -l

    Disk /dev/hdf: 320.0 GB, 320072933376 bytes
    255 heads, 63 sectors/track, 38913 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Disk /dev/hdf doesn't contain a valid partition table

    Disk /dev/hdh: 320.0 GB, 320072933376 bytes
    255 heads, 63 sectors/track, 38913 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Disk /dev/hdh doesn't contain a valid partition table
  • Crear el nuevo dispositivo del raid. Como el raid anterior era /dev/md0, este nuevo será /dev/md1. Armarse de paciencia mientras dura la creación del raid. En mi caso fueron más de 2 horas.
    shian:~# mdadm --create /dev/md1 --verbose --level=1 --raid-devices=2 /dev/hdf1 /dev/hdh1
    mdadm: size set to 312568576K
    mdadm: array /dev/md1 started.

    shian:~# cat /proc/mdstat
    Personalities : [raid1]
    md1 : active raid1 hdh1[1] hdf1[0]
    312568576 blocks [2/2] [UU]
    [>....................] resync = 0.0% (182272/312568576) finish=142.7min speed=36454K/sec
  • Formatear el raid y montarlo en un nuevo directorio. Fijaos en el tamaño disponible para datos. De los 294GB teóricos, sólo 279GB están disponibles, el resto están reservados para los metadatos e información necesaria del raid 1.
    shian:~# mkfs.ext3 /dev/md1

    shian:~# mkdir /mnt/raid_new
    shian:~# mount /dev/md1 /mnt/raid_new/

    shian:~# df -h
    S.ficheros Tamaño Usado Disp Uso% Montado en
    /dev/md0 56G 50G 2,6G 96% /mnt/raid
    /dev/md1 294G 191M 279G 1% /mnt/raid_new
  • Copiar todos los datos del antiguo raid al nuevo. Es necesario asegurarse de que no hay ningún proceso en ejecución que pueda modificar los datos mientras los copiamos. En casa es sencillo, pero en entornos con más usuarios habría que denegar las conexiones entrantes o restringirlas de alguna forma.
    shian:~# cp -a /mnt/raid /mnt/raid_new

    shian:~# df -h
    S.ficheros Tamaño Usado Disp Uso% Montado en
    /dev/md0 56G 50G 2,6G 96% /mnt/raid
    /dev/md1 294G 50G 230G 17% /mnt/raid_new
  • Como paso final, es necesario actualizar los archivos /etc/fstab y /etc/mdadm/mdadm.conf con la información del nuevo raid y eliminar las entradas correspondientes al antiguo.

  •    Una vez hecho lo anterior podemos apagar la máquina, desconectar los discos duros antiguos y arrancar de nuevo. Si todo ha ido bien, el sistema debería arrancar sin mostrar ningún error y en el mismo punto de montaje deberíamos tener disponible el nuevo raid. Ahora ya sólo nos queda empezar a llenar de nuevo el raid y dentro de dos o tres años repetir el tutorial pero esta vez con discos duros de un par de teras... ;-).

    martes, 1 de abril de 2008

    Convertir un raid 1 a un raid 5 sin formatear

       Hace un mes Javier Ros me contaba que se había montado un servidor Ubuntu en casa con un raid 1 para almacenar sus datos siguiendo mi artículo del Raid 1 en Linux. En ese mismo comentario me planteaba que se le estaba llenando el raid y que en lugar de hacer un nuevo raid 1 (puesto que necesitaba dos discos adicionales) había pensado en hacer un raid 5 añadiendo solamente un disco más. Así, me pasaba un enlace que había encontrado en el que se muestra cómo pasar de un raid 1 a un raid 5 sin necesidad de formatear y sin perder la información.

       Como sabéis, no me creo las cosas si no las pruebo. Además he estado buscando información sobre cómo funciona un raid 5 y cómo puede ser posible hacer el cambio sin perder los datos. Así, en este artículo vamos a ver un poco de teoría, posteriormente la conversión de un raid 1 a raid 5 siguiendo el tutorial inicial añadiendo mis propios comentarios, y finalmente mis impresiones sobre el raid 5.

    Un poco de Teoría
       Un raid 5 es la evolución lógica de un raid 4. Divide los datos en bloques y distribuye la paridad entre el total de discos del raid. Así, se elimina el problema del raid 4 de tener la paridad en un único disco y que éste se convierta en un cuello de botella. Este tipo de raid tiene una tolerancia a los fallos de un disco. Si uno falla el raid puede seguir funcionando y cuando se reemplaza el disco que ha fallado, se puede reconstruir la información que falta partiendo de la existente en el resto de discos.

       El cálculo de la paridad se realiza con la función lógica XOR cuya característica es que devuelve 1 si los bits de entrada son diferentes y 0 si son iguales. Esta es una característica muy importante puesto hace que dicha función sea reversible. Veámoslo con un ejemplo para que quede más claro:
     BinarioDecimal
    A11000110198
    B0010010137
    XOR11100011227

       Como hemos dicho, la función es reversible, por lo que si "le damos la vuelta":
     BinarioDecimal
    A11000110198
    B11100011227
    XOR0010010137

       Es decir, que partiendo de A y teniendo la paridad podemos calcular B. Esta propiedad también se aplica a A XOR B XOR C XOR D ... XOR N = PARIDAD, de manera que si tenemos un raid de N discos y falla cualquiera, la información que falta se puede calcular sin problemas partiendo del resto de datos y de la paridad.

       El truco para realizar la conversión consiste en que si aplicamos dicho algoritmo a dos discos, lo que obtenemos es que los dos discos se quedan en espejo!. Esto es así porque la paridad de un único bloque es él mismo, debido a que el algorimo del raid 5 necesita al menos dos bloques. Así, la única diferencia entre un raid 1 de dos discos y un raid 5 de dos discos son los metadatos. Si reemplazamos estos metadatos convertiremos el raid 1 en un raid 5.

    La parte práctica
       Ahora ya sí, con la teoría aprendida vamos a realizar la conversión. Partimos de un sistema Debian ya instalado con un raid 1 creado con 2 discos y al 99% de su capacidad.
    shian:~# df -h
    Filesystem Size Used Avail Use% Mounted on
    /dev/md3 496M 464M 6.3M 99% /mnt/md3

  • Desmontamos el raid y lo paramos.
    shian:~# umount /dev/md3
    shian:~# mdadm --stop /dev/md3
    mdadm: stopped /dev/md3
  • Creamos el raid 5 con los dos dispositivos del raid 1 (sdf1 y sdg1).
    shian:~# mdadm --create /dev/md3 --level=5 --raid-devices=2 /dev/sdf1 /dev/sdg1
    mdadm: /dev/sdf1 appears to contain an ext2fs file system
    size=524160K mtime=Wed Mar 26 16:43:27 2008
    mdadm: /dev/sdf1 appears to be part of a raid array:
    level=raid1 devices=2 ctime=Wed Mar 26 15:09:37 2008
    mdadm: /dev/sdg1 appears to contain an ext2fs file system
    size=524160K mtime=Wed Mar 26 16:43:27 2008
    mdadm: /dev/sdg1 appears to be part of a raid array:
    level=raid1 devices=2 ctime=Wed Mar 26 15:09:37 2008
    Continue creating array? y
    mdadm: array /dev/md3 started.
  • Podemos observar cómo se reconstruye el raid y en la información detallada vemos que ya es un raid 5.
    shian:~# cat /proc/mdstat
    Personalities : [raid1] [raid6] [raid5] [raid4]
    md3 : active raid5 sdg1[2] sdf1[0]
    524160 blocks level 5, 64k chunk, algorithm 2 [2/1] [U_]
    [=====>...............] recovery = 27.1% (143104/524160) finish=0.5min speed=11008K/sec

    shian:~# mdadm --detail /dev/md3
    /dev/md3:
    Version : 00.90.03
    Creation Time : Wed Mar 26 17:19:26 2008
    Raid Level : raid5
    Array Size : 524160 (511.96 MiB 536.74 MB)
    Device Size : 524160 (511.96 MiB 536.74 MB)
    Raid Devices : 2
    Total Devices : 2
    Preferred Minor : 3
    Persistence : Superblock is persistent

    Update Time : Wed Mar 26 17:20:16 2008
    State : clean
    Active Devices : 2
    Working Devices : 2
    Failed Devices : 0
    Spare Devices : 0

    Layout : left-symmetric
    Chunk Size : 64K

    UUID : df77ed88:83aa5bac:daa25bcf:b5b2c6e7
    Events : 0.2

    Number Major Minor RaidDevice State
    0 8 81 0 active sync /dev/sdf1
    1 8 97 1 active sync /dev/sdg1
  • Ahora añadimos el nuevo disco para tener los 3 que queremos en el raid 5 y ampliamos el dispositivo. Podemos comprobar que se ha añadido el nuevo disco que se está redimensionando el raid.
    shian:~# mdadm --add /dev/md3 /dev/sdh1
    mdadm: added /dev/sdh1

    shian:~# mdadm --grow /dev/md3 --raid-disks=3 --backup-file=/tmp/raid1-5.backup
    mdadm: Need to backup 128K of critical section..
    mdadm: ... critical section passed.

    shian:~# cat /proc/mdstat
    Personalities : [raid1] [raid6] [raid5] [raid4]
    md3 : active raid5 sdh1[2] sdg1[1] sdf1[0]
    524160 blocks super 0.91 level 5, 64k chunk, algorithm 2 [3/3] [UUU]
    [=>...................] reshape = 8.3% (44544/524160) finish=2.6min speed=2969K/sec
  • Forzamos la comprobación del filesystem y lo redimensionamos.
    shian:~# e2fsck -f /dev/md3
    e2fsck 1.40-WIP (14-Nov-2006)
    Pass 1: Checking inodes, blocks, and sizes
    Pass 2: Checking directory structure
    Pass 3: Checking directory connectivity
    Pass 4: Checking reference counts
    Pass 5: Checking group summary information
    /dev/md3: 20680/131072 files (0.6% non-contiguous), 491521/524160 blocks

    shian:~# resize2fs -p /dev/md3
    resize2fs 1.40-WIP (14-Nov-2006)
    Resizing the filesystem on /dev/md3 to 1048320 (1k) blocks.
    Begin pass 1 (max = 64)
    Extending the inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    The filesystem on /dev/md3 is now 1048320 blocks long.
  • Después de montar de nuevo el raid, comprobamos el nuevo tamaño (los 500MB del nuevo disco):
    shian:~# df -h
    Filesystem Size Used Avail Use% Mounted on
    /dev/md3 992M 465M 476M 50% /mnt/md3
  • No se nos puede olvidar finalmente modificar el archivo /etc/mdadm.conf para que se actualicen los datos de nuestro nuevo raid 5.
    shian:~# cd /etc/mdadm
    shian:/etc/mdadm# cp mdadm.conf mdadm.conf.`date +%y%m%d`
    shian:/etc/mdadm# echo "DEVICE partitions" > mdadm.conf
    shian:/etc/mdadm# mdadm --detail --scan >> mdadm.conf

  • Conclusiones
       Hemos visto que es posible realizar la conversión de un raid 1 a un raid 5 sin perder los datos y sin necesidad de recrear el raid desde cero. Aún así, la pregunta es ¿merece la pena pasar a un raid 5?.
       Depende. Para un entorno doméstico sin mucha carga y sin un uso muy intensivo yo diría que sí. La alternativa a tener un raid 5 pasa por un raid 10, pero en este caso ya necesitaríamos 4 discos en lugar de tres. La capacidad del volumen total sería la misma en ambos casos, pero para el raid 10 utilizaríamos un disco más!. En el lado positivo tendríamos dos discos de redundancia a fallos (uno de cada mirror), recuperaciones mucho más rápidas y mayor rendimiento.
       Por contra, el principal problema del raid 5 es el tiempo de recuperación en caso de fallo de un disco y el pobre rendimiento que obtenemos cuando se está realizando dicha recuperación. De nuevo, en un entorno doméstico esto no debería representar mayor problema, pero aún así es un hecho a tener en cuenta antes de tomar la decisión final.

    jueves, 13 de marzo de 2008

    Raid 1 en un sistema ya instalado

       En el artículo del Raid 1 en linux veíamos cómo montar un raid 1 con Debian para tener fiablidad en nuestros datos y en el caso de que fallase un disco no perderlos. De esta forma aseguramos nuestros datos, pero en caso de fallo del disco de sistema irremediablemente tendríamos que instalar de nuevo todo.

       Lo que vamos a ver en este artículo es cómo montar un raid 1 completo de todo el sistema Debian, con éste ya instalado y funcionando. De esta forma contesto a varias personas que me han pedido este artículo tanto en los comentarios del primero como por email. Para no hacer muy pesado el artículo obviaré algunas partes que están detalladas en el artículo anterior del raid 1, por lo que si algún paso no lo comprendes, por favor lee el artículo anterior para aclarar las dudas.

       Debo aclarar que este tutorial está pensado para Debian y similares por lo que en otras distribuciones no funcionará correctamente al no existir el comando update-initramfs.

    Partimos de un sistema ya instalado con tres particiones distintas: /dev/sda1 para /boot, /dev/sda5 para el swap y /dev/sda6 para /.
    Filesystem            Size  Used Avail Use% Mounted on
    /dev/sda6 7.4G 509M 6.5G 8% /
    tmpfs 63M 0 63M 0% /lib/init/rw
    udev 10M 84K 10M 1% /dev
    tmpfs 63M 0 63M 0% /dev/shm
    /dev/sda1 177M 11M 157M 7% /boot

  • Después de añadir el disco a la máquina utilizamos el truco que ya usamos en el artículo original para copiar la tabla de particiones de un disco a otro:
    shian:~# sfdisk -d /dev/sda | sfdisk /dev/sdb
    Checking that no-one is using this disk right now ...
    OK

    Disk /dev/sdb: 1044 cylinders, 255 heads, 63 sectors/track

    sfdisk: ERROR: sector 0 does not have an msdos signature
    /dev/sdb: unrecognized partition table type
    Old situation:
    No partitions found
    New situation:
    Units = sectors of 512 bytes, counting from 0

    Device Boot Start End #sectors Id System
    /dev/sdb1 63 385559 385497 83 Linux
    /dev/sdb2 385560 16771859 16386300 5 Extended
    /dev/sdb3 0 - 0 0 Empty
    /dev/sdb4 0 - 0 0 Empty
    /dev/sdb5 385623 1172744 787122 82 Linux swap / Solaris
    /dev/sdb6 1172808 16771859 15599052 83 Linux
  • Editamos con fdisk las particiones de /dev/sdb y cambiamos del tipo a fd de las número 1, 5 y 6. El resultado final es:
    ...
    Command (m for help): p

    Disk /dev/sdb: 8589 MB, 8589934592 bytes
    255 heads, 63 sectors/track, 1044 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sdb1 1 24 192748+ fd Linux raid autodetect
    /dev/sdb2 25 1044 8193150 5 Extended
    /dev/sdb5 25 73 393561 fd Linux raid autodetect
    /dev/sdb6 74 1044 7799526 fd Linux raid autodetect
  • Ahora creamos los dispositivos raid para las particiones.
    shian:~# mdadm --create /dev/md0 --level=1 --raid-disks=2 missing /dev/sdb1
    mdadm: array /dev/md0 started.
    shian:~# mdadm --create /dev/md1 --level=1 --raid-disks=2 missing /dev/sdb5
    mdadm: array /dev/md1 started.
    shian:~# mdadm --create /dev/md2 --level=1 --raid-disks=2 missing /dev/sdb6
    mdadm: array /dev/md2 started.
  • Formateamos las nuevas particiones.
    shian:~# mkfs.ext2 /dev/md0
    shian:~# mkswap /dev/md1
    shian:~# mkfs.ext3 /dev/md2
  • Actualizamos el archivo mdadm.conf con los nuevos dispositivos raid.
    shian:~# cd /etc/mdadm
    shian:/etc/mdadm# cp mdadm.conf mdadm.conf.`date +%y%m%d`
    shian:/etc/mdadm# echo "DEVICE partitions" > mdadm.conf
    shian:/etc/mdadm# mdadm --detail --scan >> mdadm.conf
  • Montamos las particiones del raid.
    shian:~# mkdir /mnt/md0
    shian:~# mkdir /mnt/md2

    shian:~# mount /dev/md0 /mnt/md0
    shian:~# mount /dev/md2 /mnt/md2
  • Editamos el archivo /etc/fstab y cambiamos sda1, sda5 y sda6 por los nuevos dispositivos del raid (md0, md1 y md2 respectivamente).
    # /etc/fstab: static file system information.
    #
    #
    proc /proc proc defaults 0 0
    /dev/md2 / ext3 defaults,errors=remount-ro 0 1
    /dev/md0 /boot ext2 defaults 0 2
    /dev/md1 none swap sw 0 0
    /dev/hdc /media/cdrom0 udf,iso9660 user,noauto 0 0
    /dev/fd0 /media/floppy0 auto rw,user,noauto 0 0
  • Editamos el archivo /boot/grub/menu.lst de configuración del grub para añadir las entradas a ambos discos duros. Duplicamos la línea que tenemos del arranque, cambiamos sda6 por md2 y cambiamos el disco duro del que arranca.
    # Línea original
    #title Debian GNU/Linux, kernel 2.6.18-4-686
    #root (hd0,0)
    #kernel /vmlinuz-2.6.18-4-686 root=/dev/sda6 ro
    #initrd /initrd.img-2.6.18-4-686
    #savedefault

    # Nuevas líneas
    title Debian GNU/Linux, kernel 2.6.18-4-686 (HD1)
    root (hd1,0)
    kernel /vmlinuz-2.6.18-4-686 root=/dev/md2 ro
    initrd /initrd.img-2.6.18-4-686
    savedefault

    title Debian GNU/Linux, kernel 2.6.18-4-686 (HD0)
    root (hd0,0)
    kernel /vmlinuz-2.6.18-4-686 root=/dev/md2 ro
    initrd /initrd.img-2.6.18-4-686
    savedefault
  • Ahora actualizamos el ramdisk para que se reflejen los cambios que hemos hecho.
    shian:~# update-initramfs -u
    update-initramfs: Generating /boot/initrd.img-2.6.18-4-686
  • Copiamos los datos de las particiones antiguas a las nuevas del raid. La opción 'x' es muy importante porque sino al copiar desde / copiaríamos todo de manera recursiva.
    shian:~# cp -ax / /mnt/md2

    shian:~# cd /boot/
    shian:/boot# cp -ax . /mnt/md0
  • Instalamos y reconfiguramos grub en los dos discos.
    shian:~# grub

    grub> root (hd0,0)
    Filesystem type is ext2fs, partition type 0x83

    grub> setup (hd0)
    Checking if "/boot/grub/stage1" exists... no
    Checking if "/grub/stage1" exists... yes
    Checking if "/grub/stage2" exists... yes
    Checking if "/grub/e2fs_stage1_5" exists... yes
    Running "embed /grub/e2fs_stage1_5 (hd0)"... 15 sectors are embedded.
    succeeded
    Running "install /grub/stage1 (hd0) (hd0)1+15 p (hd0,0)/grub/stage2 /grub/menu.lst"... succeeded
    Done.

    grub> root (hd1,0)
    Filesystem type is ext2fs, partition type 0xfd

    grub> setup (hd1)
    Checking if "/boot/grub/stage1" exists... no
    Checking if "/grub/stage1" exists... yes
    Checking if "/grub/stage2" exists... yes
    Checking if "/grub/e2fs_stage1_5" exists... yes
    Running "embed /grub/e2fs_stage1_5 (hd1)"... 15 sectors are embedded.
    succeeded
    Running "install /grub/stage1 (hd1) (hd1)1+15 p (hd1,0)/grub/stage2 /grub/menu.lst"... succeeded
    Done.
  • Y ya podemos reinicar la máquina. Hay que tenemos en cuenta que la máquina sólo arrancará del segundo disco porque el primero todavía no forma parte del raid. Si todo va bien, una vez que arranque veremos algo como esto:
    shian:~# df -h
    Filesystem Size Used Avail Use% Mounted on
    /dev/md2 7.4G 509M 6.5G 8% /
    tmpfs 63M 0 63M 0% /lib/init/rw
    udev 10M 100K 10M 1% /dev
    tmpfs 63M 0 63M 0% /dev/shm
    /dev/md0 183M 13M 161M 8% /boot

    shian:~# mount
    /dev/md2 on / type ext3 (rw,errors=remount-ro)
    tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
    proc on /proc type proc (rw,noexec,nosuid,nodev)
    sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
    udev on /dev type tmpfs (rw,mode=0755)
    tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
    devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)
    /dev/md0 on /boot type ext2 (rw)
  • Lo más difícil ya está hecho. Tenemos el raid funcionando en modo degradado porque sólo está disponible el disco sdb. Ahora repetimos casi el mismo proceso para el disco antiguo. Cambiamos el tipo de particiones a fd y las añadimos particiones al raid.
    shian:~# fdisk /dev/sda
    ...
    Command (m for help): p

    Disk /dev/sda: 8589 MB, 8589934592 bytes
    255 heads, 63 sectors/track, 1044 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sda1 1 24 192748+ fd Linux raid autodetect
    /dev/sda2 25 1044 8193150 5 Extended
    /dev/sda5 25 73 393561 fd Linux raid autodetect
    /dev/sda6 74 1044 7799526 fd Linux raid autodetect
    ...


    shian:~# mdadm --add /dev/md0 /dev/sda1
    mdadm: added /dev/sda1
    shian:~# mdadm --add /dev/md1 /dev/sda5
    mdadm: added /dev/sda5
    shian:~# mdadm --add /dev/md2 /dev/sda6
    mdadm: added /dev/sda6
  • Empezará entonces la reconstrucción de los raid.
    shian:~# cat /proc/mdstat
    Personalities : [raid1] [raid6] [raid5] [raid4]
    md2 : active raid1 sda6[2] sdb6[1]
    7799424 blocks [2/1] [_U]
    [=====>...............] recovery = 25.2% (1967936/7799424) finish=1.1min speed=81997K/sec

    md1 : active raid1 sda5[0] sdb5[1]
    393472 blocks [2/2] [UU]

    md0 : active raid1 sda1[0] sdb1[1]
    192640 blocks [2/2] [UU]

    unused devices:

  •    Un vez terminada la reconstrucción tendremos listo el sistema. Ahora, si queremos probar que todo funciona correctamente podemos reinicar de nuevo la máquina y comprobar que es capaz de arrancar desde cualquiera de los dos discos.

       Con este tipo de configuración estamos seguros de que aunque falle un disco nuestro servidor estará disponible y no tendremos que reinstalar ni reconfigurar nada. Sólo será necesario cambiar el disco defectuoso, reconstruir el raid y reconfigurar el grub.

    miércoles, 20 de febrero de 2008

    Crear paquetes deb desde otros formatos

       Cuando utilizaba RedHat, SuSE o Slackware hace algún tiempo para probar y cacharrear o simplemente para hacer las prácticas de la facultad y tenía que instalar algún programa no tenía ningún problema en compilarlo e instalarlo "a lo loco" e incluso trabajar como root. Por aquel entonces, aunque linux me gustaba sólo lo utilizaba como una ayuda durante la carrera para no tener que pasarme las horas en el centro de cálculo pegándome por un terminal VT100 de fósforo verde que me destrozaba la vista. Qué tiempos aquellos... y eso que "sólo" han pasado 10 años desde aquel 1997 en que empecé la carrera (que por cierto ya terminé).

       En fin, que compilaba, hacía make install y no me preocupaba de desinstalar ni de cómo podía quedar el sistema después de eso (total, lo reinstala y punto, no me suponía demasiado). Ahora, desde que utilizo linux como mi sistema operativo principal me preocupa que si me pongo a compilar e instalar compulsivamente o simplemente quiero probar algo, luego me resulte complicado mantener el control de lo que está instalado, desinstalarlo con facilidad,... Aunque con el magnífico apt este problema desaparece para cualquier paquete que descarguemos, en el caso de las compilaciones o de utilidades de las que no existan paquetes .deb la cosa es más compleja. Así, he descubierto un par de utilidades que me van a hacer la vida aún más fácil: alien y checkinstall.

    Alien: En ocasiones no hay paquetes en formato .deb pero sin embargo sí existen en formato .rpm. Con esta utilidad los podemos convertir a nuestro formato favorito.

    Checkinstall: Cuando compilamos un programa, el paso final suele ser make install que instala los binarios, las librerías, la ayuda del man,... En muy pocas ocasiones viene con un target uninstall del make, por lo que una posterior tarea de desinstalación suele ser algo tediosa. Checkinstall sirve para crear paquetes .deb a partir del código compilado, por lo que si posteriormente queremos desinstalar algo sólo hay que hacer un simple apt-get remove paquete.
  • Instalarlos es algo tan sencillo como:
    ivan@doraemon:~$ sudo apt-get install checkinstall alien

  • Para convertir los paquetes con alien hacemos:
    ivan@doraemon:~$ sudo alien -d paquete.rpm
  • Y una vez convertido lo podemos instalar como siempre:
    ivan@doraemon:~$ sudo dpkg -i paquete.deb

  • Si por el contrario tenemos el código fuente para compilarlo utilizaremos checkinstall, para ello hacemos:
    ivan@doraemon:~$ tar zxvf paquete.tar.gz
    ivan@doraemon:~$ cd paquete
    ivan@doraemon:~/paquete $ ./configure
    ivan@doraemon:~/paquete $ make
    ivan@doraemon:~/paquete $ sudo checkinstall
  • Y después de unas cuantas preguntas tendremos creado nuestro paquete.deb listo para instalar y mantener.
  • sábado, 8 de diciembre de 2007

    Regalo friki de cumpleaños

       Hoy cumplo 28 años y este que veis a continuación es el regalo friki (a parte de otros) que me ha hecho mi mujer (gracias cariño!). Llevaba tiempo mirando y buscando por la red para conseguir algo así y por fin hoy ya lo tengo.

       A parte de la camiseta, el paquete también es muy friki: la cinta de embalar, el remitente,... Me ha hecho especial gracia el mensaje que pone en la caja: De friki a friki.

       Y bueno, si alguien quiere hacerme algún regalo, estoy abierto a cualquier cacharro tecnológico que sea chulo y frikadas varias. Si quereis la información para enviarme un regalo escribidme un email ;-).

    jueves, 25 de octubre de 2007

    Simular un raid lineal con LVM partiendo de un disco con información

       Como continuación de la entrada anterior en la que contaba cómo crear un raid 1 a partir de un disco con datos y teniendo uno nuevo, ahora voy a responder a la pregunta que dejaba abierta al final. No obstante tengo que decir que tanto Super coco como Rubick se adelantaron a la solución en los comentarios del post.

       Si recordamos, el truco de crear el raid 1 con un único disco no funcionaba para un raid lineal, así que, ¿qué podemos hacer?. La solución que se me ha ocurrido es usar LVM. Aunque no es exactamente un raid lineal el resultado final es el mismo puesto que tenemos un único punto de montaje y la capacidad de los dos discos.

       Al igual que en el artículo anterior, no me voy a extender demasiado en los detalles puesto que mi anterior artículo sobre LVM en linux es más completo.
  • Partimos de la misma situación que en la entrada anterior. Ya existe la partición /dev/sda1 y se encuentra montada en /mnt/datos.
  • Particionamos el nuevo disco como LVM (tipo 8e).
    shian:~# fdisk /dev/sdb
    ...
    Disk /dev/sdb: 1073 MB, 1073741824 bytes
    255 heads, 63 sectors/track, 130 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sdb1 1 130 1044193+ 8e Linux LVM
    ...
  • Creamos un PV y un VG en él.
    shian:~# pvcreate /dev/sdb1
    Physical volume "/dev/sdb1" successfully created

    shian:~# vgcreate vg01 /dev/sdb1
    Volume group "vg01" successfully created
  • Ahora creamos un lvol con toda la capacidad del disco:
    shian:~# lvcreate -L 1G -n lvdatos vg01
    Logical volume "lvdatos" created
  • Lo formateamos, lo montamos y copiamos los datos que ya tenemos.
    shian:~# mkfs.ext3 /dev/vg01/lvdatos

    shian:~# mkdir /mnt/datos_lvm
    shian:~# mount /dev/vg01/lvdatos /mnt/datos_lvm/

    shian:~# cp -a /mnt/datos/* /mnt/datos_lvm/
  • No perdamos de vista el espacio que tenemos disponible:
    shian:~# df -h
    /dev/sda1 1004M 43M 911M 5% /mnt/datos
    /dev/mapper/vg01-lvdatos
    1001M 18M 932M 2% /mnt/datos_lvm
  • Ahora desmontamos la partición con los datos originales, la eliminamos y creamos una nueva de tipo LVM.
    shian:~# umount /dev/sda1
    shian:~# fdisk /dev/sda
    ...
    Disk /dev/sda: 1073 MB, 1073741824 bytes
    255 heads, 63 sectors/track, 130 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sda1 1 130 1044193+ 8e Linux LVM
  • Creamos un PV en el antiguo disco que acabamos de particionar.
    shian:~# pvcreate /dev/sda1
    Physical volume "/dev/sda1" successfully created
  • Y lo añadimos al VG que creamos al principio para ampliarlo.
    shian:~# vgextend vg01 /dev/sda1
    Volume group "vg01" successfully extended
  • Si mostramos la información del VG, podemos ver que ahora los dos discos forman parte de él y que tenemos 1016MB nuevos disponibles para utilizar, por lo que podemos ampliar el lvol.
    shian:~# vgdisplay -v vg01
    Using volume group(s) on command line
    Finding volume group "vg01"
    --- Volume group ---
    VG Name vg01
    System ID
    Format lvm2
    Metadata Areas 2
    Metadata Sequence No 3
    VG Access read/write
    VG Status resizable
    MAX LV 0
    Cur LV 1
    Open LV 1
    Max PV 0
    Cur PV 2
    Act PV 2
    VG Size 1.98 GB
    PE Size 4.00 MB
    Total PE 508
    Alloc PE / Size 254 / 1016.00 MB
    Free PE / Size 254 / 1016.00 MB
    VG UUID fYT1oQ-w6zH-z6b6-58eo-qZ39-u1Ua-vROsN4

    --- Logical volume ---
    LV Name /dev/vg01/lvdatos
    VG Name vg01
    LV UUID NBOF9q-jmfW-RCik-MH2P-0Od4-DgMR-5YRJf7
    LV Write Access read/write
    LV Status available
    # open 1
    LV Size 1016.00 MB
    Current LE 254
    Segments 1
    Allocation inherit
    Read ahead sectors 0
    Block device 253:0

    --- Physical volumes ---
    PV Name /dev/sdb1
    PV UUID yH8UHo-Vgy2-Pk9t-AozF-s1Ik-JPmL-og1kM4
    PV Status allocatable
    Total PE / Free PE 254 / 0

    PV Name /dev/sda1
    PV UUID 4cGeH2-nl7W-eH4a-mBHo-BCBI-b0np-f6gw1v
    PV Status allocatable
    Total PE / Free PE 254 / 254
  • Y finalmente lo ampliamos. Recordemos que primero ampliamos el lvol y luego el filesystem.
    shian:~# lvextend -L+1016M /dev/vg01/lvdatos
    Extending logical volume lvdatos to 1.98 GB
    Logical volume lvdatos successfully resized

    shian:~# umount /mnt/datos_lvm/

    shian:~# e2fsck -f /dev/vg01/lvdatos

    shian:~# resize2fs /dev/vg01/lvdatos
    The filesystem on /dev/vg01/lvdatos is now 520192 blocks long.
  • Y ya estaría ampliado sin necesidad de formateos.
    shian:~# df -h
    Filesystem Size Used Avail Use% Mounted on
    /dev/mapper/vg01-lvdatos
    2.0G 43M 1.9G 3% /mnt/datos_lvm

  •    Y con esto respodo a la duda inicial que me planteó Renato. Espero que te sea útil.

    viernes, 19 de octubre de 2007

    Crear un raid 1 a partir de un disco con datos sin formatear

       Hace unos días recibí un email de un lector de este blog, Renato, diciéndome que tiene un NSLU2 con Debian, qué envidía :-P, y con un disco duro muy lleno. Me preguntaba si podía añadir un nuevo disco y crear un raid sin tener que reformatear.

       Me picó la curiosidad y el resultado es este tutorial. No voy a extenderme demasiado en las explicaciones puesto que en el tutorial del raid 1 que hice hace tiempo se puede encontrar la información más detallada. Manos a la obra!.
  • Como preparación he creado una partición /dev/sda1, la he montado en /mnt/datos y he copiado algo de información en ella. Esta sería la partición que ya tenemos casi llena y no queremos tener que formatearla.
  • Vamos a crear un raid 1 con el otro disco (el disco nuevo que todavía no tiene información). Particionamos como tipo fd:
    shian:~# fdisk /dev/sdb
    ...
    Disk /dev/sdb: 1073 MB, 1073741824 bytes
    255 heads, 63 sectors/track, 130 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sdb1 1 130 1044193+ fd Linux raid autodetect
    ...
  • Y ahora viene el paso más importante en la creación del raid. Creamos el raid 1 pero con un único disco/partición. La clave es utilizar sólo la partición del nuevo disco /dev/sdb1 y en el otro poner missing, de tal forma que el raid 1 se crea degradado porque sólo existe un disco.
    shian:~# mdadm --create --verbose /dev/md1 --level=1 --raid-devices=2 /dev/sdb1 missing
    mdadm: size set to 1044096K
    mdadm: array /dev/md1 started.
  • Si aparece el error mdadm: error opening /dev/md1: No such file or directory deberemos crear el dispositivo mdX primero, según el que necesitemos:
    shian:~# mknod /dev/md0 b 9 0
    shian:~# mknod /dev/md1 b 9 1
    shian:~# mknod /dev/md2 b 9 2
    ...
  • Si miramos el fichero /proc/mdstat nos fijamos en el que raid está disponible pero sólo con un disco.
    shian:~# cat /proc/mdstat
    Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
    md1 : active raid1 sdb1[0]
    1044096 blocks [2/1] [U_]
  • Lo mismo ocurre si mostramos la información del raid:
    shian:~# mdadm --detail /dev/md1
    /dev/md1:
    Version : 00.90.03
    Creation Time : Fri Sep 28 08:09:16 2007
    Raid Level : raid1
    Array Size : 1044096 (1019.80 MiB 1069.15 MB)
    Device Size : 1044096 (1019.80 MiB 1069.15 MB)
    Raid Devices : 2
    Total Devices : 1
    Preferred Minor : 1
    Persistence : Superblock is persistent

    Update Time : Fri Sep 28 08:09:16 2007
    State : clean, degraded
    Active Devices : 1
    Working Devices : 1
    Failed Devices : 0
    Spare Devices : 0

    UUID : b0e5f96e:12266294:54e4f551:119b56e7
    Events : 0.1

    Number Major Minor RaidDevice State
    0 8 17 0 active sync /dev/sdb1
    1 0 0 1 removed
  • Formateamos el raid y lo montamos en /mnt/datos_raid. Así, estaría disponible para ser utilizado, pero con un único disco. Además, copiamos la información del disco antiguo (recordemos que está montado en /mnt/datos) al raid.
    shian:~# mkfs.ext3 /dev/md1
    shian:~#
    shian:~# mkdir /mnt/datos_raid
    shian:~# mount /dev/md1 /mnt/datos_raid
    shian:~#
    shian:~# cp -a /mnt/datos/* /mnt/datos_raid
  • En este punto ya tenemos toda la información en el raid. Ahora desmontamos la partición de nuestros datos /dev/sda1, particionamos el disco y creamos la partición de tipo raid (fd).
    shian:~# umount /dev/sda1
    shian:~# fdisk /dev/sda
    ...
    Disk /dev/sda: 1073 MB, 1073741824 bytes
    255 heads, 63 sectors/track, 130 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sda1 1 130 1044193+ fd Linux raid autodetect
    ...
  • Y ahora añadimos al raid /dev/md1 la partición que acabamos de crear:
    shian:~# mdadm --manage /dev/md1 --add /dev/sda1
    mdadm: added /dev/sda1
  • Después de un tiempo el raid estará reconstruido con toda nuestra información a salvo en ambos discos:
    shian:~# cat /proc/mdstat
    Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
    md1 : active raid1 sda1[1] sdb1[0]
    1044096 blocks [2/2] [UU]
  • El paso final es actualizar el archivo de configuración /etc/mdadm/mdadm.conf con el nuevo raid.
    shian:~# cd /etc/mdadm
    shian:/etc/mdadm# cp mdadm.conf mdadm.conf.`date +%y%m%d`
    shian:/etc/mdadm# echo "DEVICE partitions" > mdadm.conf
    shian:/etc/mdadm# mdadm --detail --scan >> mdadm.conf
  • Y añadir al archivo /etc/fstab el montaje automático del raid en el arranque.
    shian:~# echo "/dev/md1        /mnt/datos       ext3    defaults        0       2" >> /etc/fstab

  •    Hemos visto cómo pasar de una configuración con un único disco a otra basada en un raid 1 sin tener que salvar toda nuestra información en otro medio independiente y reformatear todo a la vez.

       Lamentablemente, lo que quería hacer nuestro compañero Renato era crear un raid JBOD (o lineal), cosa que no entendí yo en un primer momento y me lancé a probarlo con un raid 1. Si intentamos crear el raid lineal con un único disco vemos que no es posible. Aunque el mensaje de mdadm no es muy claro, con dmesg vemos realmente la causa:
    shian:~# mdadm --create --verbose /dev/md2 --level=linear --raid-devices=2 /dev/sdb1 missing
    mdadm: chunk size defaults to 64K
    mdadm: RUN_ARRAY failed: Invalid argument
    mdadm: stopped /dev/md2

    shian:~# dmesg
    ...
    linear: not enough drives present. Aborting!
    md: pers->run() failed ...
    md: md3 stopped.
    md: unbind
    md: export_rdev(sdb1)

       La solución a cómo poder hacer esto sin tener que reformatear en el próximo post :-).

    jueves, 31 de mayo de 2007

    Monitorizando un Raid en Linux: Estado y Ocupación

       Enlazando con el artículo anterior del envío de alarmas al móvil utilizando el API de Google Calendar, le he dado utilidad al programa. Desde hace unos días lo utilizo para monitorizar el estado del raid 1 del servidor de backup y enterarme de manera instantánea de cualquier problema con algún disco.

       Utilizando mdadm en modo monitor lo configuré para que ejecutara un script cuando detectara algún evento del raid. De todos los eventos posibles, los que a mi me interesan son:
  • Fail: Cuando se produce un fallo en algún disco del raid.
  • DegradedArray: Si se ha producido un fallo en algún disco y se ejecuta de nuevo el mdadm, se genera este evento. El caso más típico para un raid 1 es que ha fallado un disco y hemos reiniciado la máquina y estamos trabajando sólo con el otro disco. Sirve a modo de recordatorio de que hay que cambiar el disco defectuoso y reconstruir el raid.
  • RebuildStarted: Este evento se genera cuando comienza la reconstrucción del raid.
  • RebuldFinished: Cuando se ha terminado de reconstruir el raid se lanza este evento.

  •    El resto de eventos no me afectan demasiado, así que simplemente los guardaré en un log. Para ejecutar un script cuando se produce un evento en el raid en lugar de la notificación por email, es necesario hacer un pequeño cambio en el archivo /etc/init.d/mdadm.
  • Definimos la ruta del script:
    PROGRAM=/root/scripts/monitorRaid.sh
  • En "start" cambiamos la instrucción que viene por:
    start-stop-daemon -S -p $PIDFILE -x $MDADM -- -F -i $PIDFILE -p $PROGRAM -f --scan

  •    El script monitorRaid.sh que he creado es el siguiente:
    shian:~# cat scripts/monitorRaid.sh
    #!/bin/sh
    # Script de generación de alarmas según el estado del raid
    #
    # Iván López Martín
    # http://lopezivan.blogspot.com
    #####

    RAID_EVENT=$1
    LOG_DIR=/var/local/raid
    LOG_FILE=monitor_raid.log
    SMS_PROGRAM=/root/scripts/enviaSMS.sh
    GMAIL_USER=usuario@gmail.com
    GMAIL_PASS=mipassword

    if [ $RAID_EVENT == "Fail" ]; then
    date >> $LOG_DIR/$LOG_FILE
    echo Fail >> $LOG_DIR/$LOG_FILE
    echo >> $LOG_DIR/$LOG_FILE

    # Envío del SMS
    $SMS_PROGRAM $GMAIL_USER $GMAIL_PASS "ERROR CRITICO: Ha fallado un disco del raid."

    elif [ $RAID_EVENT == "DegradedArray" ]; then
    date >> $LOG_DIR/LOG_FILE
    echo DegradedArray >> $LOG_DIR/$LOG_FILE
    echo >> $LOG_DIR/$LOG_FILE

    # Envío del SMS
    $SMS_PROGRAM $GMAIL_USER $GMAIL_PASS "RECORDATORIO: El raid está funcionando con un solo disco."

    elif [ $RAID_EVENT == "RebuildStarted" ]; then
    date >> $LOG_DIR/$LOG_FILE
    echo RebuildStarted >> $LOG_DIR/$LOG_FILE
    echo >> $LOG_DIR/$LOG_FILE

    elif [ $RAID_EVENT == "RebuildFinished" ]; then
    date >> $LOG_DIR/$LOG_FILE
    echo RebuldFinished >> $LOG_DIR/$LOG_FILE
    echo >> $LOG_DIR/$LOG_FILE

    # Envío del SMS
    $SMS_PROGRAM $GMAIL_USER $GMAIL_PASS "INFO: Ha terminado la reconstrucción del raid."

    else
    date >> $LOG_DIR/$LOG_FILE
    echo $RAID_EVENT >> $LOG_DIR/$LOG_FILE
    echo >> $LOG_DIR/$LOG_FILE
    fi

       Para probar que está todo bien configurado, podemos ejecutar el monitor del raid en modo Test:
    shian:~# mdadm -F -p /root/scripts/monitorRaid.sh --scan -t -1

    shian:~# tail -3 /var/local/raid/monitor_raid.log
    Mon May 21 18:15:17 CEST 2007
    TestMessage

       Si vemos el mensaje de prueba significa que la monitorización es correcta, ahora sólo queda esperar a que falle algún disco (ojalá no ocurra) para que el programa de alarmas por sms cumpla su función.

       Adicionalmente he creado otro script que ejecuto por medio de crontab cada 10 minutos que monitoriza la ocupación de los filesystems (en este caso sólo el del raid) y cuando se supera un umbral se envía una notificación por SMS.
    shian:~# cat monitorFS.sh
    #!/bin/sh
    # Script de monitorización del tamaño de un filesystem y envío de alarmas por SMS
    #
    # Iván López Martín
    # http://lopezivan.blogspot.com
    ######

    FILESYSTEM=$1
    TMP_DIR=/root/scripts
    SMS_PROGRAM=/root/scripts/enviaSMS.sh
    GMAIL_USER=usuario@gmail.com
    GMAIL_PASS=mipassword

    SPACE_USED=`df | grep $FILESYSTEM | awk '{print $5}' | sed 's/%//g'`

    if [ "$SPACE_USED" -gt 90 ] ; then
    if ! [ -f $TMP_DIR/.fs_90 ] ;then
    SEND_SMS=YES
    THRESHOLD=90
    touch $TMP_DIR/.fs_90
    fi
    elif [ "$SPACE_USED" -gt 80 ] ; then
    if ! [ -f $TMP_DIR/.fs_80 ] ;then
    SEND_SMS=YES
    THRESHOLD=80
    touch $TMP_DIR/.fs_80
    fi
    elif [ "$SPACE_USED" -gt 70 ] ; then
    if ! [ -f $TMP_DIR/.fs_70 ] ;then
    SEND_SMS=YES
    THRESHOLD=70
    touch $TMP_DIR/.fs_70
    fi
    elif [ "$SPACE_USED" -gt 60 ] ; then
    if ! [ -f $TMP_DIR/.fs_60 ] ;then
    SEND_SMS=YES
    THRESHOLD=60
    touch $TMP_DIR/.fs_60
    fi
    fi

    if [ "$SEND_SMS" == "YES" ] ; then
    # Envio del SMS
    $SMS_PROGRAM $GMAIL_USER $GMAIL_PASS "El filesystem" $FILESYSTEM "supera el "$THRESHOLD"%."
    fi

    lunes, 14 de mayo de 2007

    Rsync vs BackupPc vs Link-Backup

       Llevo las últimas semanas buscando y probando distintos sistemas de copias de seguridad para poder tener los backups centralizados en casa en una única máquina, hacerlos de una manera eficiente, fiable y organizada. Los requisitos que debe cumplir el sistema son los siguientes:
  • Debe funcionar bajo linux: Voy a reutilizar mi antiguo Duron instalándole la nueva Debian Etch y quiero montar un raid 1 para tener fiabilidad en el backup.
  • Se deben poder hacer backups de máquinas windows y linux: Tengo que hacer backups de mi sobremesa con Ubuntu y del portatil de mi mujer con windows XP.
  • Debe permitir backups totales, parciales e incluso un histórico o versionado de archivos: Realmente lo único imprescindible es hacer un backup completo la primera vez e irlo ampliando con backups incrementales posteriores. Si además puedo tener un versionado de todos los archivos o almacenarlos en directorios distintos según el día, pues mejor que mejor.
  • No debe requerir tener el servidor encendido 24x7: No quiero un sistema de backup que deba tener encendido todo el día puesto que la idea es hacer un backup completo la primera vez y luego, según sea el trabajo diario encenderlo y hacer incrementales de vez en cuando.
  • Posibilidad de utilizar una interfaz gráfica (GUI): Más que para su utilización y/o configuración, para ver los archivos que se han almacenado de una manera fácil y cómoda.

  •    Así, con estas premisas me puse a buscar por internet y a leer foros y me quedé con tres herramientas para hacer pruebas y decidir cual era la mejor para mi: Rsync, BackupPC y Link-Backup.

    Rsync: Es un clásico en sistemas Unix/Linux. Entre las muchas opciones que permite sirve para realizar una copia de toda la información y posteriormente actualizar sólo los fragmentos que se modifican de los archivos. Cuando digo los fragmentos que se modifican de los archivos me refiero a que posteriormente, si de un archivo de 300 MB sólo modificamos una parte, sólo esa parte será enviada en la siguiente copia.
       En aspectos negativos decir que no tiene GUI de consulta de archivos.

    BackupPC: Me ha sorprendido mucho esta herramienta y además según he podido leer hay mucha gente que la utiliza con muy buenos resultados. De todos mis requisitos el único que no cumple es el de no poder apagar el servidor puesto que una vez al día ejecuta tareas de reorganización de índices y además el servidor decide cuando quiere hacer la copia de las máquinas (aunque es cierto que se pueden ejecutar backups bajo demanda). Tiene GUI para su utilización (que no configuración), versiona los archivos, permite backups completos y parciales y permite guardar la información de máquinas windows y linux. La recuperación de los archivos también está muy bien puesto que permite restaurarlos en su localización inicial, en otra máquina e incluso crear un zip con los archivos que queramos.
       Para funcionar utiliza rsync y crea hard links para reducir la utilización de espacio en el servidor. Así, la primera vez que hacemos un backup transfiere el archivo completo pero en posteriores copias, si detecta que el archivo es el mismo lo único que hace es crear un hard link, por lo que no consume más espacio en disco, pero sí inodos. Esto último, en función del sistema de archivos que utilicemos y del número de máquinas a gestionar puede traernos problemas.

    Link-Backup: Es una utilidad muy parecida a BackupPC aunque no tan "vistosa". Se trata de un script escrito en python y que también utiliza rsync para realizar la transferencia de los ficheros. Permite backups completos e incrementales y también utiliza hard links para reducir el espacio ocupado en disco. No tiene interfaz gráfica aunque en la web del autor hay disponible un pequeño cgi que sirve de interfaz gráfica para poder navegar por los distintos backups.

       Como tanto BackupPc como Link-Backup se basan en rsync y además aportan funcionalidad adicional, me centré directamente en estas dos herramientas.

       Comencé por BackupPC. Lo descargué, lo instalé y para la configuración, que fue muy sencilla, seguí este tutorial. Posteriormente cambié la configuración para utilizar rsyncd (el demonio rsync) en lugar de las transferencias cifradas por ssh. Después de un par de pequeñas pruebas transfiriendo unos cuantos archivos configuré todos los directorios a guardar y lancé el backup. En total fueron 21 GB y la copia tardó poco más de 3 horas. Durante este tiempo tuve a la vista el monitor de red de la máquina origen para comprobar la utilización de la red y he de decir que no se aprovechaba todo el ancho de banda ni mucho menos y apenas se llegó a utilizar el 40-50%. Una vez terminado el backup completo lancé el backup incremental para comprobar que se chequeaban todos los archivos y al no tener que transferir ninguno la copia se haría en pocos minutos. Al final, la copia incremental tardó 65 minutos! por lo que pensé que debía tener algo mal configurado. Estuve buscando algo más de información por internet y la conclusión a la que llegué es que BackupPC tiene que reconstruir toda la estructura de directorios, crear los hard links y actualizar su catálogo con la información de los ficheros. Además, debe calcular CRCs de los archivos para decidir si han cambiado y es necesario transferirlos de nuevo.

       El uso y configuración de Link-Backup es más sencillo todavía, sólo hay que tener python instalado para ejecutar el script. La sintaxis es similar a la del comando scp (usuario@maquina:/directorio) y no posee demasiadas opciones de configuración. Como no quería que me pasase lo mismo que con BackupPC, hice una prueba con un directorio de sólo 4 GB y los resultados fueron muchísimo mejores. Durante la transferencia la utilización de la red era de prácticamente el 90-100%, por lo que el tiempo del primer backup se redujo muchísimo. Después volví a ejecutar de nuevo el script y esta vez sí, en 5 segundos terminó indicando que no había nada que copiar.
       Luego instalé el cgi para tener la posibilidad de navegar por los backups y aunque la interfaz gráfica no se puede ni comparar con la de BackupPC, para el uso que yo quiero me sirvía.
       Cuando ya me iba a decidir por esta herramienta me dí cuenta que no era capaz de indicarle que realizara la copia de más de un directorio a la vez y crease un catálogo único, así que después de unas cuentas pruebas intentándolo, la descarté.

       Busqué alguna herramienta más por internet como Bacula pero requiere el servidor encendido y que el origen de los backups sea el servidor, por lo que también la descarté.

       Finalmente, me decidí por la opción de crearme yo mis propios scripts de backup utilizando rsync con la opción de crear hard links para ocupar menos espacio en el disco y crear un snapshot en cada ejecución.

       El script que realiza el backup se llama desde los clientes indicándole el nombre de la máquina origen por medio de ssh:
    ivan@doraemon:~$ ssh rsync@shian /home/rsync/scripts/backup.sh doraemon

       El contenido del script es el que muestro a continuación. Está algo hardcodeado porque no he sido capaz de pasarle como parámetro la lista de directorios al rsync. El problema está en que si es más de un directorio tiene que ir entre comilla simple ' y aunque "escape" el caracter con \ no funciona el rsync. Lo que hace el script es calcular el último snapshot y crear la nueva copia basándose en la anterior. Así, cada vez que lo ejecutamos se crea un nuevo directorio backup.X con la falsa ilusión de que es un backup completo por la magia de los hard links.
    #!/bin/bash

    # Comprobación de los parámetros
    if [ -z $1 ] ; then
    echo Uso `basename $0` hostname
    exit 1
    fi

    # Destino del backup
    DEST_DIR=/mnt/raid/datos

    HOST=$1
    FULL_DEST_DIR=$DEST_DIR/$HOST

    # Calculo del último snapshot del backup y del nuevo
    LAST_SNAPSHOT=`ls -ltr $FULL_DEST_DIR | tail -1 | awk {'print $8'} | cut -d . -f 2`
    ((NEW_SNAPSHOT=LAST_SNAPSHOT+1))

    # En función de la máquina de la que queramos hacer el backup, ejecutamos con unos u otros parámetros
    if [ $HOST == "doraemon" ] ; then
    rsync -av --delete --link-dest=$FULL_DEST_DIR/backup.$LAST_SNAPSHOT/ ivan@doraemon:'/Dir1 /Dir2 /Dir3' $FULL_DEST_DIR/backup.$NEW_SNAPSHOT > $FULL_DEST_DIR/files_$NEW_SNAPSHOT.txt
    mv $FULL_DEST_DIR/files_$NEW_SNAPSHOT.txt $FULL_DEST_DIR/backup.$NEW_SNAPSHOT/files.txt
    elif [ $HOST == "dorami" ] ; then
    rsync -av --delete --link-dest=$FULL_DEST_DIR/backup.$LAST_SNAPSHOT/ ana@dorami:'/MisDocs' $FULL_DEST_DIR/backup.$NEW_SNAPSHOT > $FULL_DEST_DIR/files_$NEW_SNAPSHOT.txt
    mv $FULL_DEST_DIR/files_$NEW_SNAPSHOT.txt $FULL_DEST_DIR/backup.$NEW_SNAPSHOT/files.txt
    else
    exit 2
    fi

       Lo único necesario es configurar el acceso por ssh sin password desde mi pc con linux (doraemon) y el portatil de mi mujer (dorami) al servidor de backup (shian) y desde éste a los clientes puesto que el backup parte de shian. Sé que es algo engorroso tener que configurar la conexión ssh sin password en ambos sentidos, pero prefiero hacerlo así porque quiero que el momento en el que se realice el backup se decida en el lado cliente.

       Instalé en el portatil de mi mujer Cygwin y lo configuré como sigue para conectarme por ssh sin tener que utilizar ninguna clave:
  • Primero, en windows, desde cygwin generamos el par de claves pública/privada:
    $ ssh-keygen -t dsa -b 1024
    Generating public/private dsa key pair.
    Enter file in which to save the key (/cygdrive/c/Documents and Settings/ana/.ssh/id_dsa): INTRO
    Enter passphrase (empty for no passphrase): INTRO
    Enter same passphrase again: INTRO
    Your identification has been saved in /cygdrive/c/Documents and Settings/ana/.ssh/id_dsa.
    Your public key has been saved in /cygdrive/c/Documents and Settings/ana/.ssh/id_dsa.pub.
    The key fingerprint is:
    7b:9a:c6:e9:ee:f1:2e:b0:00:fc:68:c6:58:2b:d6:a0 ana@dorami.casa
  • Copiamos la clave pública al servidor de backup:
    $ scp id_dsa.pub rsync@shian:/home/rsync/.ssh/id_dsa_ana.pub
    Password:
    id_dsa.pub 100% 605 0.6KB/s 00:00
  • Ahora nos conectamos al servidor de backup con el usuario rsync y añadimos la clave pública en el archivo de claves autorizadas para poder conectarnos por ssh sin necesidad de password:
    rsync@shian:~$ cat ~/.ssh/id_dsa_ana.pub >> ~/.ssh/authorized_keys
  • En este momento ya nos podemos conectar por ssh sin password desde la máquina windows (dorami) al servidor de backup (shian):
    $ hostname
    dorami

    $ ssh rsync@shian
    Last login: Fri 11 21:50:47 2007 from doraemon
    rsync@shian:~$
  • Para afinar un poco más la configuración y eliminar el agujero de seguridad de permitir sesiones por ssh con el usuario utilizado para el backup, editamos el archivo de claves autorizadas y añadimos al principio la limitación de sólo poder conectarnos desde esa máquina, no permitir redirección de puertos y no permitir sesiones interactivas, quedando así:
    rsync@shian:~$ cat .ssh/authorized_keys
    from="dorami.casa",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-dss AAAAB3Nza................y6SzRKqzW6V9PpwQ== ana@dorami.casa
  • De esta manera, si ahora intentamos conectarnos por ssh al servidor, obtenemos el siguiente error:
    $ ssh rsync@shian
    stdin: is not a tty

  •    Repetí los pasos desde mi máquina aunque obviamente sin la parte de capar el acceso por ssh ;-). Adicionalmente hay que hacer lo mismo para configurar las conexiones sin password pero desde el servidor hacia los clientes.

       Ahora, para finalizar, lo que hago es crear un script en cygwin para lanzar el backup y otro script .bat para crear un acceso directo en windows para que mi mujer pueda ejecutar sus backups sin ningún problema.
    # En cywin
    $ cat backupAna.sh
    #!/bin/sh
    ssh rsync@shian /home/rsync/scripts/backup.sh dorami


    # En windows
    @echo off
    REM EjecutaBackup.bat
    echo Ejecutando backup...
    C:\cygwin\bin\bash --login -i /usr/local/bin/backupAna.sh
    pause

       Y esto es todo, mi mujer puede lanzar su backup cuando quiera y yo desde mi máquina tengo un script similar.

       Como conclusiones finales me quedo con un cierto mal sabor de boca por no haber elegido BackupPc puesto que me parece la solución más completa aunque también es cierto que los tiempos de backup incrementales son bastante elevados. Aunque bastante menos elegante, la solución del script manual es mucho más eficiente y cómoda para mi.

    sábado, 21 de abril de 2007

    Linux y LVM

       En los 320GB del disco de mi nuevo pc he reservado unos 45GB para linux. En concreto me he estado esperando para instalar la nueva Ubuntu Feisty Fawn porque iba a salir en poco tiempo. Durante estos días he estado pensando cómo particionar esos 45GB y la verdad es que no lo tenía nada claro. Después de preguntar a Alex por gtalk, esta fue su solución:
    150MB /boot ext2 (o ext3)
    6GB / ext3
    1GB /var ext3
    2GB swap
    El resto en un PV de LVM para vgdata (por ejemplo). Después creas /opt en lvopt sobre vgdata y /home en lvhome sobre vgdata.
    Por último dejar el /usr en el / (no ponerlo en LVM ni como otro FS)

       Además me dió unos cuantos comandos para crear todo y me "soltó" para que probase.

       Después de mirar el man y buscar un poco por internet me enteré de qué es LVM, en qué se basa, para qué me podía servir y cómo utilizarlo. Manos a la obra...

       Como siempre, para cacharrear utilizo una máquina virtual puesto que es mucho más cómodo y permite mucha flexibilidad a la hora de añadir discos, cambiarlos de tipo,... Añadí un nuevo disco duro scsi de 2 GB (para las pruebas es más que suficiente) y me dispuse a aprender:
  • El primer paso como siempre particionar. En este caso, el tipo de partición será Linux LVM (8e)

    shian:~# fdisk /dev/sda

    Command (m for help): n
    Command action
    e extended
    p primary partition (1-4)
    p
    Partition number (1-4): 1
    First cylinder (1-261, default 1):INTRO
    Using default value 1
    Last cylinder or +size or +sizeM or +sizeK (1-261, default 261):INTRO
    Using default value 261

    Command (m for help): t
    Selected partition 1
    Hex code (type L to list codes): 8e
    Changed system type of partition 1 to 8e (Linux LVM)

    Command (m for help): p

    Disk /dev/sda: 2147 MB, 2147483648 bytes
    255 heads, 63 sectors/track, 261 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sda1 1 261 2096451 8e Linux LVM

    Command (m for help): w
    The partition table has been altered!

    Calling ioctl() to re-read partition table.
    Syncing disks.
  • El siguiente paso es crear el Physical Volume (PV):
    shian:~# pvcreate -v /dev/sda1
    Set up physical volume for "/dev/sda1" with 4192518 available sectors
    Zeroing start of device /dev/sda1
    Physical volume "/dev/sda1" successfully created
  • Ahora creamos el Volume Group (VG) con el PV recien creado. En mi caso crearé sólo uno:
    shian:~# vgcreate -v vg01 /dev/sda1
    Adding physical volume '/dev/sda1' to volume group 'vg01'
    Archiving volume group "vg01" metadata.
    Creating volume group backup "/etc/lvm/backup/vg01"
    Volume group "vg01" successfully created
  • Después creamos los Logical Volume (LV) que queramos. Cada uno de estos será al final un punto de montaje distinto. En mi caso crearé uno de 1 GB para datos (y dejaré el otro GB libre):
    shian:~# lvcreate -v -L 1G -n lvdatos vg01
    Finding volume group "vg01"
    Creating logical volume lvdatos
    Archiving volume group "vg01" metadata.
    Creating volume group backup "/etc/lvm/backup/vg01"
    Found volume group "vg01"
    Loading vg01-lvdatos
    Zeroing start of logical volume "lvdatos"
    Creating volume group backup "/etc/lvm/backup/vg01"
    Logical volume "lvdatos" created

  •    Bien, veamos lo que llevamos hecho hasta ahora.
  • Lista de PVs creados:
    shian:~# pvdisplay -v
    Scanning for physical volume names
    --- Physical volume ---
    PV Name /dev/sda1
    VG Name vg01
    PV Size 2.00 GB / not usable 0
    Allocatable yes
    PE Size (KByte) 4096
    Total PE 511
    Free PE 255
    Allocated PE 256
    PV UUID 1wounc-DIHj-Tf54-4h2c-4rcB-w137-gLH4I6
  • Lista de VGs creados. En VG Size vemos que el VG es de 2GB y que hemos utilizado 1GB (Alloc Size):
    shian:~# vgdisplay
    --- Volume group ---
    VG Name vg01
    System ID
    Format lvm2
    Metadata Areas 1
    Metadata Sequence No 2
    VG Access read/write
    VG Status resizable
    MAX LV 0
    Cur LV 1
    Open LV 0
    Max PV 0
    Cur PV 1
    Act PV 1
    VG Size 2.00 GB
    PE Size 4.00 MB
    Total PE 511
    Alloc PE / Size 256 / 1.00 GB
    Free PE / Size 255 / 1020.00 MB
    VG UUID BpNJTl-9tlr-DjzM-C8Mb-LfnL-NWDa-uyWDpf
  • Lista de LVols creados:
    shian:~# lvdisplay -v
    Finding all logical volumes
    --- Logical volume ---
    LV Name /dev/vg01/lvdatos
    VG Name vg01
    LV UUID 7CYTLY-YgI2-c64S-F50h-vPXH-TEk9-o4hFOE
    LV Write Access read/write
    LV Status available
    # open 0
    LV Size 1.00 GB
    Current LE 256
    Segments 1
    Allocation inherit
    Read ahead sectors 0
    Block device 254:0
  • Y finalmente, si queremos ver la asignación de VGs, LVols y PVs:
    shian:~# vgdisplay -v
    Finding all volume groups
    Finding volume group "vg01"
    --- Volume group ---
    VG Name vg01
    System ID
    Format lvm2
    Metadata Areas 1
    Metadata Sequence No 2
    VG Access read/write
    VG Status resizable
    MAX LV 0
    Cur LV 1
    Open LV 0
    Max PV 0
    Cur PV 1
    Act PV 1
    VG Size 2.00 GB
    PE Size 4.00 MB
    Total PE 511
    Alloc PE / Size 256 / 1.00 GB
    Free PE / Size 255 / 1020.00 MB
    VG UUID BpNJTl-9tlr-DjzM-C8Mb-LfnL-NWDa-uyWDpf

    --- Logical volume ---
    LV Name /dev/vg01/lvdatos
    VG Name vg01
    LV UUID 7CYTLY-YgI2-c64S-F50h-vPXH-TEk9-o4hFOE
    LV Write Access read/write
    LV Status available
    # open 0
    LV Size 1.00 GB
    Current LE 256
    Segments 1
    Allocation inherit
    Read ahead sectors 0
    Block device 254:0

    --- Physical volumes ---
    PV Name /dev/sda1
    PV UUID 1wounc-DIHj-Tf54-4h2c-4rcB-w137-gLH4I6
    PV Status allocatable
    Total PE / Free PE 511 / 255

  •    Después de este pequeño resumen seguimos con la creación de la partición.
  • Una vez que tenemos el lvol creado lo formateamos con la sistema de ficheros que más nos guste:
    shian:~# mkfs.ext3 /dev/vg01/lvdatos
    mke2fs 1.37 (21-Mar-2005)
    Filesystem label=
    OS type: Linux
    Block size=4096 (log=2)
    Fragment size=4096 (log=2)
    131072 inodes, 262144 blocks
    13107 blocks (5.00%) reserved for the super user
    First data block=0
    8 block groups
    32768 blocks per group, 32768 fragments per group
    16384 inodes per group
    Superblock backups stored on blocks:
    32768, 98304, 163840, 229376

    Writing inode tables: done
    Creating journal (8192 blocks): done
    Writing superblocks and filesystem accounting information: done

    This filesystem will be automatically checked every 27 mounts or
    180 days, whichever comes first. Use tune2fs -c or -i to override.
  • Lo montamos para probar:
    shian:~# mkdir /mnt/datos_lvm
    shian:~# mount /dev/vg01/lvdatos /mnt/datos_lvm
    shian:~# df -h /mnt/datos_lvm/
    Filesystem Size Used Avail Use% Mounted on
    /dev/mapper/vg01-lvdatos
    1008M 33M 925M 4% /mnt/datos_lvm
  • Y listo, ya sólo queda añadirlo a /etc/fstab para que se monte automáticamente en el arranque:
    shian:~# echo "/dev/vg01/lvdatos /mnt/datos_lvm ext3   defaults        0       2" >> /etc/fstab

  •    Hasta aquí es lo fácil. Como se puede ver con unos cuantos comandos tenemos el filesystem montado y listo para ser utilizado sin mayores complicaciones.

       La ventaja de utilizar lvm es que podemos redimensionar las particiones de manera dinámica sin tener que hacer un backup de la información, tener que reparticionar,... Vamos a probarlo.
  • Creamos un archivo aleatorio de 25MB, calculamos su CRC y lo apuntamos:
    shian:~# dd if=/dev/urandom of=/mnt/datos_lvm/random count=51200
    51200+0 records in
    51200+0 records out
    26214400 bytes transferred in 7.991592 seconds (3280248 bytes/sec)
    shian:~# cksum /mnt/datos_lvm/random
    1105592823 26214400 /mnt/datos_lvm/random
  • Supongamos que necesitamos espacio adicional en el disco, por ejemplo, 500MB más. Lo que tenemos que hacer es ampliar el lvol y después el filesystem:
    shian:~# lvextend -v -L+500M /dev/vg01/lvdatos
    Finding volume group vg01
    Archiving volume group "vg01" metadata.
    Extending logical volume lvdatos to 1.49 GB
    Creating volume group backup "/etc/lvm/backup/vg01"
    Found volume group "vg01"
    Found volume group "vg01"
    Loading vg01-lvdatos
    Logical volume lvdatos successfully resized
  • En el caso de un sistema de archivos como ext3 es necesario desmontarlo primero antes de realizar la ampliación. Adicionalmente también es necesario ejecutar e2fsck para chequear el filesystem:
    shian:~# umount /mnt/datos_lvm/
    shian:~# resize2fs /dev/vg01/lvdatos
    resize2fs 1.37 (21-Mar-2005)
    Please run 'e2fsck -f /dev/vg01/lvdatos' first.

    shian:~# e2fsck -f /dev/vg01/lvdatos
    e2fsck 1.37 (21-Mar-2005)
    Pass 1: Checking inodes, blocks, and sizes
    Pass 2: Checking directory structure
    Pass 3: Checking directory connectivity
    Pass 4: Checking reference counts
    Pass 5: Checking group summary information
    /dev/vg01/lvdatos: 12/131072 files (0.0% non-contiguous), 18737/262144 blocks

    shian:~# resize2fs /dev/vg01/lvdatos
    resize2fs 1.37 (21-Mar-2005)
    Resizing the filesystem on /dev/vg01/lvdatos to 390144 (4k) blocks.
    The filesystem on /dev/vg01/lvdatos is now 390144 blocks long.
  • Y ya estaría listo. Si ahora montamos el filesystem y/o comprobamos el lvol vemos que tiene 500MB más:
    shian:~# mount /mnt/datos_lvm/
    shian:~# df -h /mnt/datos_lvm/
    Filesystem Size Used Avail Use% Mounted on
    /dev/mapper/vg01-lvdatos
    1.5G 58M 1.4G 4% /mnt/datos_lvm

    shian:~# lvdisplay
    --- Logical volume ---
    LV Name /dev/vg01/lvdatos
    VG Name vg01
    LV UUID 7CYTLY-YgI2-c64S-F50h-vPXH-TEk9-o4hFOE
    LV Write Access read/write
    LV Status available
    # open 0
    LV Size 1.49 GB
    Current LE 381
    Segments 1
    Allocation inherit
    Read ahead sectors 0
    Block device 254:0
  • Para reducirlo el procedimiento es similiar, pero hay que tener en cuenta que primero hay que reducir el filesystem y luego el lvol. La primera vez que lo hice no lo pensé mucho y reduje primero el lvol, por lo que me cargué los datos ;-)
    shian:~# umount /mnt/datos_lvm/
    shian:~# e2fsck -f /dev/vg01/lvdatos
    e2fsck 1.37 (21-Mar-2005)
    Pass 1: Checking inodes, blocks, and sizes
    Pass 2: Checking directory structure
    Pass 3: Checking directory connectivity
    Pass 4: Checking reference counts
    Pass 5: Checking group summary information
    /dev/vg01/lvdatos: 12/196608 files (0.0% non-contiguous), 20795/390144 blocks

    shian:~# resize2fs /dev/vg01/lvdatos 1G
    resize2fs 1.37 (21-Mar-2005)
    Resizing the filesystem on /dev/vg01/lvdatos to 262144 (4k) blocks.
    The filesystem on /dev/vg01/lvdatos is now 262144 blocks long.

    shian:~# lvreduce -v -L-500M /dev/vg01/lvdatos
    Finding volume group vg01
    WARNING: Reducing active logical volume to 1.00 GB
    THIS MAY DESTROY YOUR DATA (filesystem etc.)
    Do you really want to reduce lvdatos? [y/n]: y
    Archiving volume group "vg01" metadata.
    Reducing logical volume lvdatos to 1.00 GB
    Creating volume group backup "/etc/lvm/backup/vg01"
    Found volume group "vg01"
    Found volume group "vg01"
    Loading vg01-lvdatos
    Logical volume lvdatos successfully resized

    shian:~# mount /mnt/datos_lvm/
    shian:~# df -h /mnt/datos_lvm/
    Filesystem Size Used Avail Use% Mounted on
    /dev/mapper/vg01-lvdatos
    1008M 58M 921M 6% /mnt/datos_lvm
  • Comprobamos el cksum para ver que no nos hemos cargado nada:
    shian:~# cksum /mnt/datos_lvm/random
    1105592823 26214400 /mnt/datos_lvm/random

  •    Aunque todo parece muy bonito, no fue tan fácil. Como he dicho al principio del artículo el disco virtual que añadí al vmware era scsi por lo que cuando arrancaba la máquina, como los controladores scsi se cargan posteriormente al montaje de las particiones aparecía un error porque no encontraba el dispositivo. Como no estaba seguro que de fuera eso añadí un nuevo disco ide, repetí todos los pasos y funcionó a la perfección. Así, el problema era del scsi. Lo que tuve que hacer para solucionarlo fue:
  • Miré el controlador scsi que utiliza vmware y los módulos cargados:
    shian:~# lspci
    0000:00:00.0 Host bridge: Intel Corp. 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (rev 01)
    0000:00:01.0 PCI bridge: Intel Corp. 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge (rev 01)
    0000:00:07.0 ISA bridge: Intel Corp. 82371AB/EB/MB PIIX4 ISA (rev 08)
    0000:00:07.1 IDE interface: Intel Corp. 82371AB/EB/MB PIIX4 IDE (rev 01)
    0000:00:07.3 Bridge: Intel Corp. 82371AB/EB/MB PIIX4 ACPI (rev 08)
    0000:00:0f.0 VGA compatible controller: VMWare Inc [VMWare SVGA II] PCI Display Adapter
    0000:00:10.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)
    0000:00:11.0 Ethernet controller: Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE] (rev 10)

    shian:~# lsmod
    Module Size Used by
    ipv6 241728 -
    ehci_hcd 28744 -
    usbcore 127804 -
    shpchp 34416 -
    pci_hotplug 14784 -
    intel_agp 23084 -
    pcnet32 31972 -
    mii 5392 -
    crc32 3888 -
    agpgart 33472 -
    raid1 20912 -
    md_mod 72172 -
    sd_mod 19552 -
    dm_mod 55692 -
    mptspi 16348 -
    mptscsih 24720 -
    mptbase 52064 -
    scsi_transport_spi 23792 -
    scsi_mod 145484 -
    ide_cd 40200 -
    cdrom 39424 -
    unix 25328 -
    ext3 126488 -
    jbd 54552 -
    ide_disk 16112 -
    generic 4952 -
    piix 10228 -
    ide_core 117252 -
    evdev 9824 -
  • La clave me la dio el MPT tanto de la controladora como de los módulos cargados:
    0000:00:10.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)

    ...
    mptspi 16348 -
    mptscsih 24720 -
    mptbase 52064 -
    ...
  • Así, añadí al archivo /etc/modules lo siguiente:
    # /etc/modules: kernel modules to load at boot time.
    #
    # This file should contain the names of kernel modules that are
    # to be loaded at boot time, one per line. Comments begin with
    # a "#", and everything on the line after them are ignored.
    ide-cd
    ide-disk
    mptspi
    mptscsih
    mptbase
  • Guardé los cambios, reinicié y ahora ya sí se inicializaba la tarjeta scsci antes del lvm y al intentar montar las particiones éstas estaban disponibles.


  •    Otra de las cosas interesantes que podemos hacer con lvm es crear un volumen físico sobre uno de raid. Aprovechando el raid 1 que cree hace tiempo hice la siguiente prueba. Ojo que los datos del raid se pierden!.
    shian:~# umount /dev/md0
    shian:~# pvcreate -v /dev/md0
    Set up physical volume for "/dev/md0" with 2096000 available sectors
    Zeroing start of device /dev/md0
    Physical volume "/dev/md0" successfully created

    shian:~# vgcreate -v vg02 /dev/md0
    Adding physical volume '/dev/md0' to volume group 'vg02'
    Archiving volume group "vg02" metadata.
    Creating volume group backup "/etc/lvm/backup/vg02"
    Volume group "vg02" successfully created

    shian:~# lvcreate -v -L 900M -n lvol_raid vg02
    Finding volume group "vg02"
    Creating logical volume lvol_raid
    Archiving volume group "vg02" metadata.
    Creating volume group backup "/etc/lvm/backup/vg02"
    Found volume group "vg02"
    Loading vg02-lvol_raid
    Zeroing start of logical volume "lvol_raid"
    Creating volume group backup "/etc/lvm/backup/vg02"
    Logical volume "lvol_raid" created

    shian:~# mkfs.ext3 /dev/vg02/lvol_raid
    mke2fs 1.37 (21-Mar-2005)
    Filesystem label=
    OS type: Linux
    Block size=4096 (log=2)
    Fragment size=4096 (log=2)
    115200 inodes, 230400 blocks
    11520 blocks (5.00%) reserved for the super user
    First data block=0
    8 block groups
    32768 blocks per group, 32768 fragments per group
    14400 inodes per group
    Superblock backups stored on blocks:
    32768, 98304, 163840, 229376

    Writing inode tables: done
    Creating journal (4096 blocks): done
    Writing superblocks and filesystem accounting information: done

    This filesystem will be automatically checked every 28 mounts or
    180 days, whichever comes first. Use tune2fs -c or -i to override.

    shian:~# mount /dev/vg02/lvol_raid /mnt/raid

    shian:~# df -h /mnt/raid
    Filesystem Size Used Avail Use% Mounted on
    /dev/mapper/vg02-lvol_raid
    886M 17M 825M 2% /mnt/raid

       Y ya tenemos un LVM + Raid 1 funcionando y con las ventajas de ambos: la redundancia del raid y la gestión dinámica de las particiones de lvm.

       Finalmente, para terminar, otra cosa que se puede hacer con lvm es lo siguiente (cortesía de Alex). Imaginemos que tenemos lvm montado en un disco, con particiones, datos,... pero que se nos está quedando pequeño. Nos compramos un disco nuevo para sustituir al antiguo (en el ejemplo he añadido un nuevo disco scsi a la máquina virtual de 4GB, sdb) y después de particionarlo como lvm hacemos lo siguiente:
  • Creamos un PV en la nueva partición:
    shian:~# pvcreate -v /dev/sdb1
    Set up physical volume for "/dev/sdb1" with 8385483 available sectors
    Zeroing start of device /dev/sdb1
    Physical volume "/dev/sdb1" successfully created
  • Lo añadimos al VG vg01 ya existente:
    shian:~# vgextend -v vg01 /dev/sdb1
    Checking for volume group "vg01"
    Archiving volume group "vg01" metadata.
    Adding physical volume '/dev/sdb1' to volume group 'vg01'
    Volume group "vg01" will be extended by 1 new physical volumes
    Creating volume group backup "/etc/lvm/backup/vg01"
    Volume group "vg01" successfully extended
  • Mostramos la información y comprobamos que tenemos dos PVs en el mismo VG. Nos fijamos en las extensiones disponibles en cada uno:
    shian:~# vgdisplay -v vg01
    Using volume group(s) on command line
    Finding volume group "vg01"
    --- Volume group ---
    VG Name vg01
    System ID
    Format lvm2
    Metadata Areas 2
    Metadata Sequence No 5
    VG Access read/write
    VG Status resizable
    MAX LV 0
    Cur LV 1
    Open LV 1
    Max PV 0
    Cur PV 2
    Act PV 2
    VG Size 5.99 GB
    PE Size 4.00 MB
    Total PE 1534
    Alloc PE / Size 256 / 1.00 GB
    Free PE / Size 1278 / 4.99 GB
    VG UUID BpNJTl-9tlr-DjzM-C8Mb-LfnL-NWDa-uyWDpf

    --- Logical volume ---
    LV Name /dev/vg01/lvdatos
    VG Name vg01
    LV UUID 7CYTLY-YgI2-c64S-F50h-vPXH-TEk9-o4hFOE
    LV Write Access read/write
    LV Status available
    # open 1
    LV Size 1.00 GB
    Current LE 256
    Segments 1
    Allocation inherit
    Read ahead sectors 0
    Block device 254:0

    --- Physical volumes ---
    PV Name /dev/sda1
    PV UUID 1wounc-DIHj-Tf54-4h2c-4rcB-w137-gLH4I6
    PV Status allocatable
    Total PE / Free PE 511 / 255

    PV Name /dev/sdb1
    PV UUID N0nwct-jNnY-eU0D-6Evh-tkIN-9vKs-9KsV3v
    PV Status allocatable
    Total PE / Free PE 1023 / 1023
  • Movemos la información de la partición que queremos liberar. Previamente nos aparece un error indicando que necesitamos tener activado en el kernel el mirror, así que cargamos el módulo:
    shian:~# pvmove -v /dev/sda1
    Finding volume group "vg01"
    Archiving volume group "vg01" metadata.
    Creating logical volume pvmove0
    mirror: Required device-mapper target(s) not detected in your kernel

    shian:~# modprobe dm_mirror
  • De nuevo, intentamos mover los datos, aunque ahora sí lo conseguimos:
    shian:~# pvmove -v /dev/sda1
    Finding volume group "vg01"
    Archiving volume group "vg01" metadata.
    Creating logical volume pvmove0
    Moving 256 extents of logical volume vg01/lvdatos
    Found volume group "vg01"
    Updating volume group metadata
    Creating volume group backup "/etc/lvm/backup/vg01"
    Found volume group "vg01"
    Found volume group "vg01"
    Loading vg01-pvmove0
    Found volume group "vg01"
    Loading vg01-lvdatos
    Checking progress every 15 seconds
    /dev/sda1: Moved: 72.7%
    /dev/sda1: Moved: 100.0%
    Found volume group "vg01"
    Found volume group "vg01"
    Found volume group "vg01"
    Loading vg01-pvmove0
    Found volume group "vg01"
    Loading vg01-lvdatos
    Found volume group "vg01"
    Found volume group "vg01"
    Removing temporary pvmove LV
    Writing out final volume group after pvmove
    Creating volume group backup "/etc/lvm/backup/vg01"
  • Comprobamos el estado del VG y vemos que el PV /dev/sda1 tiene todas las extensiones disponibles:
    shian:~# vgdisplay -v vg01
    ...
    ...
    --- Physical volumes ---
    PV Name /dev/sda1
    PV UUID 1wounc-DIHj-Tf54-4h2c-4rcB-w137-gLH4I6
    PV Status allocatable
    Total PE / Free PE 511 / 511

    PV Name /dev/sdb1
    PV UUID N0nwct-jNnY-eU0D-6Evh-tkIN-9vKs-9KsV3v
    PV Status allocatable
    Total PE / Free PE 1023 / 767
  • Y finalmente eliminamos el PV /dev/sda1 del VG vg01 y comprobamos el resultado:
    shian:~# vgreduce -v vg01 /dev/sda1
    Finding volume group "vg01"
    Using physical volume(s) on command line
    Archiving volume group "vg01" metadata.
    Removing "/dev/sda1" from volume group "vg01"
    Creating volume group backup "/etc/lvm/backup/vg01"
    Removed "/dev/sda1" from volume group "vg01"

    shian:~# vgdisplay -v vg01
    Using volume group(s) on command line
    Finding volume group "vg01"
    --- Volume group ---
    VG Name vg01
    System ID
    Format lvm2
    Metadata Areas 1
    Metadata Sequence No 11
    VG Access read/write
    VG Status resizable
    MAX LV 0
    Cur LV 1
    Open LV 1
    Max PV 0
    Cur PV 1
    Act PV 1
    VG Size 4.00 GB
    PE Size 4.00 MB
    Total PE 1023
    Alloc PE / Size 256 / 1.00 GB
    Free PE / Size 767 / 3.00 GB
    VG UUID BpNJTl-9tlr-DjzM-C8Mb-LfnL-NWDa-uyWDpf

    --- Logical volume ---
    LV Name /dev/vg01/lvdatos
    VG Name vg01
    LV UUID 7CYTLY-YgI2-c64S-F50h-vPXH-TEk9-o4hFOE
    LV Write Access read/write
    LV Status available
    # open 1
    LV Size 1.00 GB
    Current LE 256
    Segments 1
    Allocation inherit
    Read ahead sectors 0
    Block device 254:0

    --- Physical volumes ---
    PV Name /dev/sdb1
    PV UUID N0nwct-jNnY-eU0D-6Evh-tkIN-9vKs-9KsV3v
    PV Status allocatable
    Total PE / Free PE 1023 / 767

  •    En este extenso (si has llegado hasta aquí enhorabuena) artículo hemos visto qué es el LVM y cómo gestionarlo.

       Tengo que admitir que durante mis pruebas me he cargado alguna vez algo pero nada que no se pueda arreglar empezando de nuevo. Además, si finalmente me decido a utilizarlo en casa ya me andaré con más cuidado y pensaré bien lo que hago antes de estropearlo. Todavía no tengo muy claro si lo haré o no porque en caso de fallo no creo que sea lo mismo intentar recuperar una partición ext3 que una lvm, en fín, me tendré que informar.