sexta-feira, 17 de julho de 2015

Como recuperei meus dados de um Volume LVM

Introdução

Resumindo em poucas palavras perdi meu volume LVM, fiz várias besteiras na tentativa de recuperá-lo e quando achei que estava tudo perdido, meu amigo Ariel me deu as ferramentas necessárias para resolver a questão.

As soluções apresentadas aqui não vão se aplicar a qualquer situação de perdas de dados de LVM, mas podem ser a solução se o seu cenário for próximo do meu.

Cenário

Dois discos instalados no notebook

/dev/sda:
/boot - Partição padrão ext4
swap - Partição padrão swap
/ - Partição LVM VG1
/home - Partição LVM VG1

/dev/sdb:
/Dados - Partição LVM VG1

O meu cenário era relativamente simples, um VG compreendendo ambos os discos, sendo que o LV que eu queria recuperar estava isolado no /dev/sdb, aliás, fica a dica: evite quebrar seus LVs em mais de um disco, caso seja possível. Eu acredito que as soluções apresentadas podem funcionar para outros cenários, mas não testei isso! O objetivo aqui é apenas relatar como recuperei o meu cenário.

Criar uma imagem do disco

Esse passo é fundamental, independente de qual solução você escolher, a primeira coisa que você deve fazer é gerar um clone do seu disco.
dd if=/dev/sdX of=/mnt/sdX.img bs=512 conv=noerror,sync

No meu caso:
# dd if=/dev/sdb of=/mnt/sdb.img bs=512 conv=noerror,sync

Onde /mnt é um HD externo, outro disco, uma unidade de rede, enfim, um lugar com espaço suficiente para armazenar uma cópia completa (mesmo tamanho) do seu disco.

Esse processo vai demorar, vai demorar muito... Meu HD de míseros 320 GB demorou mais de 10 horas. Não pule esse passo, se nada funcionar você ainda pode voltar essa cópia para o mesmo disco (ou outro) e envia-lo para uma empresa especializada em recuperação de dados.

Primeira Solução - Montar a imagem do disco de forma direta

Na ordem cronológica do meu caso, essa foi a segunda solução encontrada, mas ela é mais simples, então aconselho você a começar por ela.

Basicamente o que vamos fazer é montar a imagem que temos do disco no sistema e restaurar nossos dados para outro disco.

Essa solução também é um pouco mais limitada: só dá para usá-la caso seu LV esteja alocado em uma faixa contínua no disco, ou seja, se ele tiver apenas um segmento, e estiver situado em apenas um dos discos. Para saber se o seu LV tem apenas um segmento contínuo, veja mais abaixo o dump do metadado feito a partir do início da partição LVM.

# mkdir /Dados2
# mount -o loop,ro,offset=$((2*1024*1024)) /run/media/deo/IMG/Déo/sdb.img /Dados2


O comando mount acima abre um sistema de arquivos contido em uma imagem (arquivo sdb.img), fazendo sua associação a um ponto de montagem. O detalhe importante é a opção offset que ignora os primeiros n bytes do arquivo de imagem. Neste caso foi tentado o valor de 2MB, afim de ignorar o primeiro MB entre o início do disco e a primeira partição e também 1 MB referente ao metadado da partição LVM. Caso você tente usar esse comando, se o mount pedir para você informar o sistema de arquivos, é porque não funcionou, não perca tempo tentando especificá-lo. Dá para tentar também variações como 3*... 4*..., em fim, pode ser que o seu metadado seja maior.

É possivel também que você precise aumentar o offset, caso o LV em questão não esteja no início da partição. Nesse caso some ao valor acima o valor do start_extent multiplicado pelo extent_size, que podem ser encontrados no metadado, discutido mais abaixo.

# ls -las /Dados2
total 23927780
      4 drwxr-xr-x. 10 deo  deo        4096 Jun 14 17:44 .
      4 dr-xr-xr-x. 20 root root       4096 Jun 23 15:29 ..
      4 drwx------.  2 deo  deo        4096 Mar 24 08:47 centos-6.5-pe-3.7.0-ptb2.13-vbox
8388648 -rw-------.  1 deo  deo  8592031744 Jan  4 00:57 CentOS 7 - Zabbix Server.vdi
8388648 -rw-------.  1 deo  deo  8592031744 Jan 28 00:13 CentOS Scripts.vdi

# df -kh
Sist. Arq.                Tam. Usado Disp. Uso% Montado em
/dev/loop0                294G   93G  186G  34% /Dados2

Segunda Solução - Extrair as informações referentes ao LVM do disco

É isso mesmo que você leu, o LVM guarda uma cópia das configurações dele no início de cada partição integrante do VG, aquele 1MB de metadado do LVM da primeira solução ;-), foi essa solução que salvou a minha pele.

Vamos extrair as primeiras 500 linhas do disco, você pode fazer isso com um live cd por exemplo. Esse arquivo possui os dados que serão a base para recriarmos o nosso volume.
strings -t x /dev/sdX | head -500 > string_dev_sdX.txt

No meu caso:
# strings -t x /dev/sdb | head -500 > string_dev_sdb.txt

Agora você precisa criar um volume LVM na sua máquina, ou instalar o HD que você quer recuperar em uma máquina com LVM funcional. No meu caso eu reinstalei o sistema no /dev/sda criando a mesma estrutura: /boot, swap, / e /home. Como a partição /Dados estava em outro disco, e em somente em um disco, eu não precisei me preocupar muito.

Recapitulando o que temos até agora:
  • Sistema funcional com LVM;
  • Disco que desejo recuperar instalado na máquina;
  • Arquivo que vamos utilizar para recriar os apontamentos.

Carregar o módulo
# modprobe dm-mod

Exibir os volumes físicos:
# pvs -v
    Scanning for physical volume names
  PV         VG     Fmt  Attr PSize   PFree   DevSize PV UUID
  /dev/sda2  fedora lvm2 a--  111,59g      0  111,59g 1r10wL-sh0C-KcAF-K9XB-ji2L-hzbM-UBhEDL
  /dev/sdb1         lvm2 a--  298,09g 298,09g 298,09g uYRucm-f2aK-Ye0q-C2Db-QYpg-aw2z-9sBGV3


O que nos interessa é o PV UUID, nesse caso "uYRucm-f2aK-Ye0q-C2Db-QYpg-aw2z-9sBGV3". E o nome do VG funcional, no meu caso "fedora".

Agora é a etapa final, mas antes de mais nada BACKUP:
# cp /etc/lvm/backup/fedora /etc/lvm/backup/fedora_02
# cp /etc/lvm/archive/fedora_00000-427671572.vg /etc/lvm/archive/fedora_2_00000-427671572.vg


Esses arquivos, são os arquivos que o LVM utiliza para controlar quais são os volumes, partições, pontos de montagem e etc.

Ao abrir o arquivo string_dev_sdb.txt, encontramos as informações referentes ao pv1:
 102594 pv1 {
 10259a id = "uYRucm-f2aK-Ye0q-C2Db-QYpg-aw2z-9sBGV3"
 1025c8 device = "/dev/sdb1"
 1025de status = ["ALLOCATABLE"]
 1025f7 flags = []
 102602 dev_size = 625140400
 102617 pe_start = 2048
 102627 pe_count = 76310

Remova todo esse código hexadecimal, faça as devidas indentações, feche as chaves que estão faltando e, transforme os dados nisso:
                pv1 {
                        id = "uYRucm-f2aK-Ye0q-C2Db-QYpg-aw2z-9sBGV3"
                        device = "/dev/sdb1"

                        status = ["ALLOCATABLE"]
                        flags = []
                        dev_size = 625140400
                        pe_start = 2048
                        pe_count = 76310
                }

Agora procure no arquivo string_dev_sdb.txt, as informações referentes ao ponto de montagem dados:
 1029b1 dados {
 1029b9 id = "SdiIbs-5dcB-hZkU-ykcW-cXy0-EIdr-5DNBwZ"
 1029e7 status = ["READ", "WRITE", "VISIBLE"]
 102a0d flags = []
 102a18 creation_host = "deonote"
 102a32 creation_time = 1411552196
 102a4d segment_count = 1
 102a60 segment1 {
 102a6b start_extent = 0
 102a7c extent_count = 76310
 102a92 type = "striped"
 102aa3 stripe_count = 1
 102ab5 stripes = [
 102ac1 "pv1", 0

Remova todo esse código hexadecimal, faça as devidas indentações, feche as chaves que estão faltando e, transforme os dados nisso:
                dados {
                        id = "SdiIbs-5dcB-hZkU-ykcW-cXy0-EIdr-5DNBwZ"
                        status = ["READ", "WRITE", "VISIBLE"]
                        flags = []
                        creation_host = "localhost"
                        creation_time = 1411552196
                        segment_count = 1

                        segment1 {
                                start_extent = 0
                                extent_count = 76310

                                type = "striped"
                                stripe_count = 1

                                stripes = [
                                        "pv1", 0
                                ]
                        }
                }

Essas entradas devem ser inseridas nos dois arquivos:
/etc/lvm/backup/fedora
/etc/lvm/archive/fedora_00000-427671572.vg

MUITA, mas muita atenção na posição em que as informações devem ser inseridas.

Testando a recuperação do volume:
# vgcfgrestore fedora --test -f /etc/lvm/archive/fedora_00000-427671572.vg
  TEST MODE: Metadata will NOT be updated and volumes will not be (de)activated.
  Restored volume group fedora


Observação:
O meu VG se chama fedora, você deve alterar o comando de acordo com o nome do seu VG. Nenhuma mensagem de erro? Então você fez tudo certinho, caso contrário, reveja suas configurações.

Recuperando o volume:
# vgcfgrestore fedora -f /etc/lvm/archive/fedora_00000-427671572.vg
  Restored volume group fedora


Verificando o status do volume:
# lvscan
  ACTIVE            '/dev/fedora/root' [9,77 GiB] inherit
  ACTIVE            '/dev/fedora/swap' [512,00 MiB] inherit
  ACTIVE            '/dev/fedora/home' [101,32 GiB] inherit
  inactive          '/dev/fedora/dados' [298,09 GiB] inherit


Ativando o volume:
#  vgchange -ay
  4 logical volume(s) in volume group "fedora" now active


Verificando o status do volume:

# lvscan
  ACTIVE            '/dev/fedora/root' [9,77 GiB] inherit
  ACTIVE            '/dev/fedora/swap' [512,00 MiB] inherit
  ACTIVE            '/dev/fedora/home' [101,32 GiB] inherit
  ACTIVE            '/dev/fedora/dados' [298,09 GiB] inherit


Montando o volume:

# mkdir /Dados
# mount /dev/fedora/dados /Dados/


Verificando os dados:
# ls -l /Dados/
total 23927780
      4 drwxr-xr-x. 10 deo  deo        4096 Jun 14 17:44 .
      4 dr-xr-xr-x. 20 root root       4096 Jun 23 15:29 ..
      4 drwx------.  2 deo  deo        4096 Mar 24 08:47 centos-6.5-pe-3.7.0-ptb2.13-vbox
8388648 -rw-------.  1 deo  deo  8592031744 Jan  4 00:57 CentOS 7 - Zabbix Server.vdi
8388648 -rw-------.  1 deo  deo  8592031744 Jan 28 00:13 CentOS Scripts.vdi

# df -kh
Sist. Arq.                Tam. Usado Disp. Uso% Montado em
/dev/mapper/fedora-dados  294G   93G  186G  34% /Dados

Outros cenários

Caso seu problema seja mais complexo, talvez por ter dividido o LV entre os discos, ou então tenha um LV com vários segmentos, decorrente de expansões alternadas de diferentes volumes lógicos, creio que ainda assim seja possível fazer algum procedimento para sua recuperação. Se conseguir fazer o dump do metadado e tiver o conteúdo do disco razoavelmente preservado, o pior que pode acontecer é você ter que calcular o início e final de cada segmento, recortá-los, possívelmente com um dd, especificando valores para skip e count, e juntá-los na ordem correta.

Escrito a 4 mãos pelo mestre Ariel e por esse humilde ser, dono do blog ;-)

Referencias

PissedOffAdmins
ADAMS BROS BLOG
serverfault.com

Nenhum comentário: