Header Ads

Disco virtual

Existen muchos métodos para crear y montar máquinas virtuales y también muchos formatos. Por lo general utilizamos hipervisores para crearlas y ponerlas en producción. Pero hablamos de sistemas completos virtualizados.
Y si solo queremos crear un  disco virtual vacío, bien sea para almacenar archivos o para crear unidades de disco en red y muchos otros usos. En este caso, muchos afirman que compartir un disco físico es mejor, más fiable y simple, y tienen toda la razón, pero hay algunos escenarios en que tenemos un solo disco y necesitamos crear volúmenes independientes para el manejo de archivos privados y públicos para muchos usuarios o propósitos, y para lograrlo tendríamos que hacer tantas particiones como volúmenes necesitemos, en cambio, los discos virtuales, al ser tratados por los sistemas operativos como archivos, podrían ser una buena alternativa de solución, ya que es mejor tener muchos discos virtuales (archivos) dentro de un solo disco físico, que un disco físico con un montón de particiones. Y sin mencionar que es más sencillo hacer un backup de un disco virtual que de un físico.
Existen muchos formatos para los discos virtuales, tales como .vhd o .vhdx (Microsoft Virtual PC / Hyper-V), .vmdk (VMware), .vdi (Oracle VirtualBox),  .img (archivos binarios), etc, etc; algunos de los cuales pertenecen al estándar abierto Open Virtualization Format.
Estos discos se crean en dependencia de su tamaño, por ejemplo Fixed Size (Tamaño Fijo. Este formato es el más parecido a un disco físico. Tienen un tamaño establecido en su creación, sin importar la cantidad de datos), Dynamically Expanding (Expansión Dinámica. Se incrementa a medida que el disco se va llenando) y Differencing (Diferenciales), siendo los de Tamaño Fijo los más confiables.
Para crearlos podemos hacer uso de hipervisores, como Virtualbox, pero el procedimiento es algo engorroso, ya que primero hay que crear la VM y luego convertir el disco de formato VDI a otro formato más amigable como IMG.
VBoxManage clonehd --format RAW MyDisk.vdi MyDisk.img
Y luego montarlo en dependencia del tipo de partición que tengan:
mount -t ntfs -o loop,rw MyDisk.img /mnt
El rey por excelencia para estos menesteres es Gparted...
Gparted Interface
Que con su potente e intuitiva interfaz gráfica podemos particionar nuestros discos virtuales de acuerdo a nuestras necesidades.
GParted Create Partition
Sin embargo, para aquellos que no disponen de entorno gráfico está  Parted, ideal para trabajar por terminal.
Advertencia:
Antes de avanzar debemos aclarar algo. Recomendaremos el uso de formatos de imágenes flexibles y dinámicos, como VHD/VHDX (vea sus diferencias en el post  Comprender y trabajar con archivos VHD/X), VDI (nativo de Virtualbox. Lea Cómo montar la imagen de disco de VirtualBox (VDI) para acceder al sistema de archivos de VM en Ubuntu), entre otros, sin embargo en este post nos referiremos exclusivamente al  formato .img, no porque sea mejor o peor que los anteriores, sino porque es más universal,  por ser binario, y a la creación de estas imágenes con el programa dd
Existen otras opciones para crear imágenesestas imágenes rápidamente, tales como:
truncate -s 10G 10GB_HDD.img
fallocate -l 10G 10GB_HDD.img
Pero debe saber que  truncate se usa en un sistema de archivos que admita archivos dispersos (como ext4), pero fallocate no. Un archivo disperso es aquel en el que las unidades de asignación que componen el archivo no se asignan realmente hasta que se utilizan, sin embargo, los metadatos del archivo ocuparán un espacio considerable. Este tipo de archivo tiene ventajas y desventajas. Un archivo no disperso tiene sus bloques (unidades de asignación) asignados con anticipación. Además ni fallocate, ni truncate pueden establecer el contenido del archivo a un valor especificado, como es el caso de dd, en cambio, el contenido de un archivo asignado con fallocate o truncate puede ser cualquier valor de basura que existía en las unidades asignadas durante la creación y este comportamiento puede o no ser deseado. Adicionalmente estas opciones tienen limitaciones en cuanto a su uso en determinados sistemas de archivos.
fallocate es similar a dd, en cuanto a que ambos pre-asignan bloques a un archivo, pero, a diferencia de dd, que escribe ceros en estos bloques, fallocate se limita a pre-asignar el espacio, si escribir el archivo. 
dd es el más lento, ya que en realidad escribe el valor o fragmento de datos a toda la secuencia de archivo como se especifica con ella son las opciones de línea de comandos, pero es más seguro. Hay limitación en cuanto al tamaño (máx 2GB), pero existe un truco y es asignar el tamaño en megabytes a la opción  count. Por ejemplo:
# 4GB size in megabytes
dd if=/dev/urandom of=4GB_HDD.img bs=1M count=4096
						
						
						
# 10GB size in megabytes dd if=/dev/urandom of=10GB_HDD.img bs=1M count=10240
En el siguiente ejemplo, vamos a automatizar la creación de un disco virtual en formato .img. Lo podemos adaptar, cambiando los valores de las variables. Por ejemplo, el script establece mydisk.img como el nombre de la imagen, la partición msdos y 1 GB de tamaño (o sea 1024) y la etiqueta de la partición mydisk. Y al lanzar la pregunta sobre el sistema de archivos, debemos escribir: ext4, fat32, ntfs o  hfs (puede agregar más opciones):
#!/bin/bash
# variables
myuser=user # your user account
mountpoint="/home/$myuser/disk" # path to mount point folder
pathimg="/home/$myuser/img" # path to .img folder
vdisk="$pathimg/mydisk.img" # path .img file
vptable="msdos" # msdos, gpt
vsize="1024" # MB/MiB
vlabel=mydisk # disk label
vbs="1M" # 1M or 1k/2k/4k/16k
ptype="primary" # primary/logical/extended

# create path if doesn't exist
if [ ! -d $route ]; then mkdir -p $route; chmod a+rwx -R * $route; fi
if [ ! -d $pathimg ]; then mkdir -p $pathimg; chmod a+rwx -R * $pathimg; fi

# create img
dd if=/dev/zero | pv | dd of=$vdisk iflag=fullblock bs=$vbs count=$vsize && sync

# format ntfs/fat32/ext4
function pntfs(){
 parted $vdisk \
   mklabel $vptable \
   mkpart $ptype ntfs 2048s 100% \
   set 1 lba on \
   align-check optimal 1
 mkntfs -Q -v -F -L "$vlabel" $vdisk
 ntfsresize -i -f -v $vdisk
 ntfsresize --force --force --no-action $vdisk
 ntfsresize --force --force $vdisk
 fdisk -lu $vdisk
}
function pfat32(){
 parted $vdisk \
   mklabel $vptable \
   mkpart $ptype fat32 2048s 100% \
   set 1 lba on \
   align-check optimal 1
 mkfs.fat -F32 -v -I -n "$vlabel " $vdisk
 fsck.fat -a -w -v $vdisk
 fdisk -lu $vdisk
}
function pext4(){
 parted $vdisk \
   mklabel $vptable \
   mkpart $ptype 2048s 100%
 mkfs.ext4 -F -L "$vlabel" $vdisk
 parted -s $vdisk align-check optimal 1
 e2fsck -f -y -v -C 0 $vdisk
 resize2fs -p $vdisk
 fdisk -lu $vdisk
}
function phfs(){
 # for mac
 #apt-get install hfsutils
 hformat -l "$vlabel" $vdisk
 #To mount
 #mount -t hfs -o loop image.img mountpoint
}
read -p "Enter File System (e.g. ntfs, fat32, ext4, hfs): " pset
    case $pset in
        "ntfs")
            pntfs
        ;;
        "fat32")
            pfat32
        ;;
        "ext4")
            pext4
        ;;
        "hfs")
            phfs
        ;;
     *)
   echo "unknown option"
    ;;
esac
Si no va a utilizar el 100% del espacio del disco, sino un espacio específico, reemplace:
mkpart primary $vptable 2048s 100%
Por:
mkpart primary $vptable 1 $vsize
Donde $vsize es la variable que almacena el tamaño exacto del disco que va a usar, en MB/MiB.
Nota: Si utiliza GPT en lugar de msdos, hay cambios significativos, por tanto el script deberá adaptarlo o no le servirá, ya que GPT no admite particiones extendidas/lógicas. Para mayor información pulse  AQUI
Montaje del Disco Virtual
Hay varias maneras de montar un disco virtual, ya sea de forma automática, con el inicio del sistema o manualmente.
Nota: reemplace "/path_to/" o /path_to/mountpoint" por las rutas hacia la imagen de disco y carpeta de montaje
Método 1: GUI
Linux utiliza  Loop Device para el tratamiento de las imágenes de disco (ISO, IMG, etc). Los loops son dispositivos de bucle (/dev/loop*) que hacen que los archivos sean accesibles como dispositivos de bloque (Para mayor información visite  How to use loop devices.). Por tanto, montar el disco virtual .img es similar a como si lo hiciéramos con una imagen .ISO (botón derecho sobre la imagen .img, y seleccionar "montador de imágenes de disco") y el sistema la enviará al loop que esté desocupado.
Método 2: Terminal
También puede montarla desde la consola a un punto de anclaje específico. Tenga en cuenta que "mount" requiere privilegios, por tanto, si no está trabajando desde root, o quiere que el usuario desde el que trabaja tenga acceso a la carpeta, debe cambiar el propietario de la misma y habilitar su escritura:
mount -o loop,rw,sync /path_to/filename.img /path_to/mountpoint 
sudo chown $USER:$USER /path_to/mountpoint
sudo chmod 777 /path_to/mountpoint
También puede montar el disco virtual especificando el loop:
losetup loop1 /path_to/filename.img
Pero es importante que verifique la disponibilidad del loop antes y después de montar el disco virtual:
ls /dev/loop*
losetup --list
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop1      0      0         0    0 /path_to/filename.img
Si queremos verificar la imagen montada en loop con Gparted:
sudo -H gparted /dev/loopx
Y para desmontar:
# umount
sudo losetup -d /dev/loopx
Proceso completo con  losetup:
losetup -f
/dev/loop8
sudo losetup -P /dev/loop8 /path_to/filename.img
sudo losetup -l
/dev/loop8         0      0         0  0 /path_to/filename.img                            0     512
# edit /etc/fstab and put the line:
# /path/to/loop/device       /path_to/mountpoint       auto       loop       0 0
# example:
/dev/loop8 /path_to/mountpoint ext4      defaults      0 0
# and:
sudo mount -a
Método 3: Con bindfs
sudo mkdir /mnt/disk
# edit fstab and add line:
/path_to/filename.img /mnt/disk auto    defaults  0   0
sudo mount -a
sudo -u $USER bindfs -n /mnt/disk /path_to/mountpoint
Método 4: bash script (recomendado)
#!/bin/bash
myuser="user" # your user
dst="/home/$myuser/vdisk" # path to mount point
img="/home/$myuser/img/test.img" # path to .img file

case "$1" in
  'start')
    # mount
    echo "Mounting Virtual Disk..."
    # create destination folder if doesn't exist
    if [ ! -d "$dst" ]; then sudo -u "$myuser" mkdir -p "$dst"; fi > /dev/null
    # mount
    mount -v -o loop "$img" "$dst"
    echo "Virtual Disk Mount: $(date)" | tee -a /var/log/syslog
 ;;
  'stop')
    echo "Umounting Virtual Disk..."
    # umount
    umount "$dst"
    echo "Virtual Disk Umount: $(date)" | tee -a /var/log/syslog
 ;;
  *)
	echo "Usage: $0 { start | stop }"
 ;;
esac
Para iniciarlo o detenerlo:
sudo ./mountimg.sh start
sudo ./mountimg.sh stop
Para iniciarlo con el sistema, edite crontab y agregue la tarea:
sudo crontab -e
@reboot /path_to/mountimg.sh start
Uniendo ambos scripts:
Este es un bash script que unifica tanto el montaje/desmontaje de la imagen, como su creación. Se usa 
sudo ./vdisk.sh start
sudo ./vdisk.sh stop
Cambie las variables y valores según sus necesidades:
#!/bin/bash
# This script create, format and mount/umount Virtual Hard Disk (VHD) image (.img)

# check dependencies
pkg='libnotify-bin'
if apt-get -qq install $pkg; then
    echo "OK"
else
    echo "Error installing $pkg. Abort"
    exit
fi

# CHANGE VALUES AND PATHS
# your user account
myuser="your_user"
# path to mount point folder (change it)
mountpoint="/home/$myuser/vdisk"
# path to .img folder (change it)
myvhd="/home/$myuser/myvhd"
# path to .img file (e.g: 4GB_HDD.img) (change it)
myimg="$myvhd/1GB_HDD.img"
# choose type: msdos, gpt
vptable="msdos"
# Large .img file in MB/MiB (e.g: 4096 = 4GB)
vsize="1024"
# disk label
vlabel="mydisk"
# 1M or 1k/2k/4k/16k
vbs="1M"
# partition: primary/logical/extended
ptype="primary"

# create and format disk .img
function create_img(){
    # create img
    dd if=/dev/zero | pv | dd of=$myimg iflag=fullblock bs=$vbs count=$vsize && sync
    # format ntfs
    function pntfs(){
     parted $myimg \
       mklabel $vptable \
       mkpart $ptype ntfs 2048s 100% \
       set 1 lba on \
       align-check optimal 1
     mkntfs -Q -v -F -L "$vlabel" $myimg
     ntfsresize -i -f -v $myimg
     ntfsresize --force --force --no-action $myimg
     ntfsresize --force --force $myimg
     fdisk -lu $myimg
    }
    # format fat32
    function pfat32(){
     parted $myimg \
       mklabel $vptable \
       mkpart $ptype fat32 2048s 100% \
       set 1 lba on \
       align-check optimal 1
     mkfs.fat -F32 -v -I -n "$vlabel " $myimg
     fsck.fat -a -w -v $myimg
     fdisk -lu $myimg
    }
    # format ext4
    function pext4(){
     parted $myimg \
       mklabel $vptable \
       mkpart $ptype 2048s 100%
     mkfs.ext4 -F -L "$vlabel" $myimg
     parted -s $myimg align-check optimal 1
     e2fsck -f -y -v -C 0 $myimg
     resize2fs -p $myimg
     fdisk -lu $myimg
    }
    # format hfs
    function phfs(){
     # for mac
     #apt-get install hfsutils
     hformat -l "$vlabel" $myimg
     # To mount
     #mount -t hfs -o loop image.img mountpoint
    }
    read -p "Enter File System (e.g. ntfs, fat32, ext4, hfs): " pset
        case $pset in
            "ntfs")
                pntfs
            ;;
            "fat32")
                pfat32
            ;;
            "ext4")
                pext4
            ;;
            "hfs")
                phfs
            ;;
         *)
       echo "unknown option"
        ;;
    esac
}

case "$1" in
  'start')
    # if no mount point exists, create it 
    if [ ! -d $mountpoint ]; then mkdir -p $mountpoint; chmod a+rwx -R * $mountpoint; fi
    # if no img folder exists, create it 
    if [ ! -d $myvhd ]; then mkdir -p $myvhd; chmod a+rwx -R * $myvhd; fi
    # if no .img exists, create it 
    if [ ! -f $myimg ]; then create_img; fi
    # mount .img
    echo "Mount VHD-IMG..."
    mount -o loop,rw,sync "$myimg" "$mountpoint"
    chmod a+rwx -R * "$mountpoint"
    notify-send "VHD-IMG Mount:" "$(date)" -i checkbox 
    echo "VHD-IMG Mount: $(date)" | tee -a /var/log/syslog
 ;;
  'stop')
    # umount .img
    echo "Umount VHD-IMG..."
    umount "$mountpoint"
 ;;
  *)
	echo "Usage: $0 { start | stop }"
 ;;
esac
Método 5: Con kpartx
kpartx, un pequeño programa que detecta las particiones en una imagen de disco y genera en /dev/loopXX los mapeos necesarios para poder montarlas como si fueran particiones en un disco real. 
Lista el mapeo de particiones que se agregarían con la opción -a
kpartx -l mydisk.img
Agrega/Monta la partición del disco virtual en /dev/loopXX (según el comando anterior):
kpartx -a mydisk.img
Para crear (verificar si existe el mapeo, de lo contrario hágalo en el loop):
mkfs.ext4 /dev/loopXX
Elimina/desmonta el mapeo de la partición:
kpartx -d mydisk.img
A continuación un script para montar/desmontar una imagen con kpartx
#!/bin/bash
# Mount/Umount .img with kpartx
# your user account
myuser="user"
# path to mount point folder
mountpoint="/home/$myuser/vdisk"
# path to .img folder
myvhd="/home/$myuser/ssd/test"
# path to .img file (e.g: 4GB_HDD.img)
myimg="$myvhd/1GB_HDD.img"

case "$1" in
    'start')
    # mount .img
    echo "Mount VHD-IMG..."
    kpartx -a -v "$myimg"
    for f in $(losetup --list | grep "$myvhd" | awk '{print $1}'); do mount $f "$mountpoint"; done
 ;;
    'stop')
    # umount .img
    echo "Umount VHD-IMG..."
    umount "$mountpoint"
    if [ -n "`kpartx -d -v "$myimg"`" ]; then
        echo "VHD-IMG Umount: $(date)" | tee -a /var/log/syslog
    else
        echo "No Mounted Image"
    fi
 ;;
*)
echo "Usage: $0 { start | stop }"
 ;;
esac
Para más opciones visite  Kpartx
Importante
- Para los casos de discos virtuales con varias particiones, lo más recomendado es realizar el proceso directamente en el dispositivo de bucle /dev/loopXX en lugar de la imagen .img, ya que el comando mkfs eventualmente podría destruir las particiones. Para estos casos utilice el script de  GracefulRestart
- También puede crear la imagen de disco virtual con Gparted, siguiendo el tutorial de Kos
- Otro script similar es el imgKreator de Nagren
- Los scripts bash están diseñados para crear/montar/desmontar .im con una sola partición primaria
- Para más opciones lea  parted (8) - Linux Man Pages
- En algunas versiones de Ubuntu y en algunos administradores de archivos, si monta la imagen .img directamente a un directorio con fstab, puede aparecer duplicada, por tanto no se recomienda
- Para montar una imagen de disco .img en Windows podemos usar la aplicación  OSFMount
OSFMount


Con la tecnología de Blogger.