LVM: cómo reducir un volume group quitando un physical volume

Extender un grupo de volúmenes (vgroup) de LVM es muy sencillo, únicamente tenemos que crear una nueva partición con fdisk, asignarle el tipo 8e (Linux LVM), crear un volumen físico con la partición y luego extender el grupo de volúmenes, algo así:

# fdisk -cu /dev/sda
...
...
# pvcreate /dev/sda1
# vgextend vg_group1 /dev/sda1

Reducir un Volume Group

Reducir un grupo de volúmenes no es mucho más complicado, pero sí hay que tener en cuenta ciertas pautas. Para poder sacar un volumen físico (Physical volume) de un grupo de volúmenes es necesario que ese PV no tenga ningún physical extent (PE) ocupado. Es decir, hay que mover esos PV a otro physical volumen antes de sacarlo del grupo de volúmenes. En el siguiente ejemplo tenemos un grupo de volúmenes llamado vg_testing con dos volúmenes físicos (sdb1 y sdc1). Atentos a los valores Total PE y Free PE:

# pvdisplay 
  --- Physical volume ---
  PV Name               /dev/sdb1
  VG Name               vg_testing
  PV Size               100.00 MiB / not usable 4.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              24
  Free PE               0
  Allocated PE          24
  PV UUID               ltxr2Z-3RiY-3Z4q-CAp0-6Jk7-n6Yx-BGw4kU

  --- Physical volume ---
  PV Name               /dev/sdc1
  VG Name               vg_testing
  PV Size               256.00 MiB / not usable 4.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              63
  Free PE               63
  Allocated PE          0
  PV UUID               4n1cjE-Q2Jl-yHeC-6jny-FsPg-Ts1k-QxZYwp

Como podéis observar, /dev/sdb1 tiene ocupados sus 24 PE (todo el espacio de la partición) mientras que /dev/sdc1 no tiene ninguno en uso. Si quisiéramos reducir el volumen quitando el PV /dev/sdc1 lo podríamos hacer sin problemas, ya que está no se ha usado ningún PE del mismo por los volúmenes lógicos que están dentro del grupo de volúmenes. El comando sería el siguiente (añado -v para verbose):

# vgreduce -v vg_testing /dev/sdc1
    Finding volume group "vg_testing"
    Using physical volume(s) on command line
    Archiving volume group "vg_testing" metadata (seqno 17).
    Removing "/dev/sdc1" from volume group "vg_testing"
    Creating volume group backup "/etc/lvm/backup/vg_testing" (seqno 18).
  Removed "/dev/sdc1" from volume group "vg_testing"

¿Pero si el disco que queremos sacar del VG es /dev/sdb1? En ese caso lo que debemos hacer antes de hacer el vgreduce es mover todos los datos (PE) que están almacenados en ese volumen físico a otro volumen físico del mismo grupo de volúmenes. Podemos elegir a que PV moverlo o que el sistema lo mueva automáticamente. Hay que verificar que el VG cuenta con PV (Physical volumes) con suficientes PE (Physical extents) para almacenar esos datos. Una vez verificado usamos el comando pvmove para mover los PE. Añado (-v) verbose y que nos indique cada dos segundos el estado del proceso (-i 2):

# pvmove -i 2 -v /dev/sdb1
    Finding volume group "vg_testing"
    Archiving volume group "vg_testing" metadata (seqno 19).
    Creating logical volume pvmove0
    Moving 13 extents of logical volume vg_testing/lv_testing
    Found volume group "vg_testing"
    activation/volume_list configuration setting not defined, checking only host tags for vg_testing/lv_testing
    Updating volume group metadata
    Found volume group "vg_testing"
    Found volume group "vg_testing"
    Creating vg_testing-pvmove0
    Loading vg_testing-pvmove0 table (253:4)
    Loading vg_testing-lv_testing table (253:3)
    Suspending vg_testing-lv_testing (253:3) with device flush
    Suspending vg_testing-pvmove0 (253:4) with device flush
    Found volume group "vg_testing"
    activation/volume_list configuration setting not defined, checking only host tags for vg_testing/pvmove0
    Resuming vg_testing-pvmove0 (253:4)
    Found volume group "vg_testing"
    Loading vg_testing-pvmove0 table (253:4)
    Suppressed vg_testing-pvmove0 identical table reload.
    Resuming vg_testing-lv_testing (253:3)
    Creating volume group backup "/etc/lvm/backup/vg_testing" (seqno 20).
    Checking progress before waiting every 2 seconds
  /dev/sdb1: Moved: 7.7%
  /dev/sdb1: Moved: 100.0%
    Found volume group "vg_testing"
    Found volume group "vg_testing"
    Loading vg_testing-lv_testing table (253:3)
    Loading vg_testing-pvmove0 table (253:4)
    Suspending vg_testing-lv_testing (253:3) with device flush
    Suspending vg_testing-pvmove0 (253:4) with device flush
    Found volume group "vg_testing"
    Resuming vg_testing-pvmove0 (253:4)
    Found volume group "vg_testing"
    Resuming vg_testing-lv_testing (253:3)
    Found volume group "vg_testing"
    Removing vg_testing-pvmove0 (253:4)
    Removing temporary pvmove LV
    Writing out final volume group after pvmove
    Creating volume group backup "/etc/lvm/backup/vg_testing" (seqno 22).

Una vez realizado esto, verificaríamos que no hay ningún PE en uso en ese Physical volume y que han pasado a otro PV del grupo de volúmenes:

# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sdb1
  VG Name               vg_testing
  PV Size               100.00 MiB / not usable 4.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              24
  Free PE               24
  Allocated PE          0
  PV UUID               ltxr2Z-3RiY-3Z4q-CAp0-6Jk7-n6Yx-BGw4kU

  --- Physical volume ---
  PV Name               /dev/sdc1
  VG Name               vg_testing
  PV Size               256.00 MiB / not usable 4.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              63
  Free PE               50
  Allocated PE          13
  PV UUID               4n1cjE-Q2Jl-yHeC-6jny-FsPg-Ts1k-QxZYwp

Ya sólo quedaría el último paso, sacar el volumen físico del grupo de volúmenes:

# vgreduce -v vg_testing /dev/sdb1
    Finding volume group "vg_testing"
    Using physical volume(s) on command line
    Archiving volume group "vg_testing" metadata (seqno 24).
    Removing "/dev/sdb1" from volume group "vg_testing"
    Creating volume group backup "/etc/lvm/backup/vg_testing" (seqno 25).
  Removed "/dev/sdb1" from volume group "vg_testing"

Si el Volume Group tiene LVM Snapshots…

Según he podido comprobar (¡que alguien me corrija si me equivoco!) pvmove no es compatible con LVM snapshots. Voy a crear un snapshot de un logical volume que tengo en el VG vg_testing:

# lvcreate -n lv_testing_SNAP -s /dev/vg_testing/lv_testing -L 40M
  Logical volume "lv_testing_SNAP" created

Y si intento hacer el pvmove ahora:

# pvmove -v /dev/sdc1
    Finding volume group "vg_testing"
    Archiving volume group "vg_testing" metadata (seqno 30).
    Creating logical volume pvmove0
  Skipping snapshot-related LV lv_testing
  Skipping snapshot-related LV lv_testing_SNAP
  All data on source PV skipped. It contains locked, hidden or non-top level LVs only.
  No data to move for vg_testing

Así que parece un bug (o que no es una característica posible de momento), a no ser que exista otra forma de hacerlo sin necesidad de eliminar los snapshots.