Discuta este tópico no fórum

Se este conteúdo te ajudou, deixe um presente!

sábado, 6 de abril de 2013

OpenWRT: Compartilhando seu HD na rede pelo roteador(NAS)

A porta USB no roteador o torna muito versátil. Um dos usos mais interessantes é transformá-lo em um NAS (Network Attached Storage) ou, em suma, um "HD na rede". Para tal, vamos precisar de um roteador com porta USB, uma unidade de armazenamento USB e espaço em disco para instalar o servidor de arquivos.


Depois de conectar um HD externo e, talvez, aumentar o espaço do disco do OpenWRT para poder instalar mais coisas, vamos a instalação do servidor de arquivos. O servidor de arquivos padrão para o Linux é o Samba. Apesar de ser uma implementação do protocolo "padrão" da Microsoft para troca de arquivos em rede, é o que temos de melhor para troca de arquivos mesmo entre duas máquinas Linux. Se o cliente for um Windows®, nem se fala.

Já existe um pacote pronto do samba para o OpenWRT. Basta instalar o pacote samba36-server e, opcionalmente, luci-app-samba, e você terá tudo que precisa para o servidor. Você pode usar tanto a interface WEB como a linha de comando para a instalação:
opkg update
opkg install samba36-server
A configuração do samba pode ser feita com as opções do arquivo smb.conf ou, de forma mais limitada, pela infraestrutura do OpenWRT, no arquivo "/etc/config/samba" . Vou me limitar ao segundo caso pois atenderá a maioria dos usuários. Quanto ao primeiro, não seria diferente de um sistema Linux padrão. Preferencialmente altere o arquivo "/etc/samba/smb.conf.template" pois a configuração final será obtida juntando as informações deste arquivo com o que for configurado em "/etc/config/samba". O pacote luci-app-samba, opcional, fornece uma página na interface WEB Luci que possibilita a configuração básica do samba ou a edição do arquivo "smb.conf.template" sem precisar saber usar o vim.

Na inteface WEB, assim como no arquivo de configuração, é bom definir o nome e o grupo de trabalho do seu roteador. Os diretórios compartilhados são criados em um item sambashare ou em "Diretórios Compartilhados" na interface Luci. Caso a segurança não seja preocupação, ative a opção "permitir convidados" ou "guest_ok". Assim, não será necessário fornecer um usuário e senha para conectar no roteador. A opção "somente leitura" vai no mesmo sentido. Só lembrando que, por padrão, usuário sem senha assume o usuário unix nobody e este precisa ter permissão de leitura ou escrita ou diretório para poder acessar ou escrever nos diretórios. Se a segurança não for importante, dê acesso completo a todos os usuários:
chmod a+rw /mnt/sd??
Onde o /mnt/sd?? é o local onde seu disco está montado no sistema. Só lembre que ao liberar o acesso sem senha e com permissão de escrita a todos, seus arquivos estarão acessíveis a qualquer usuário que tenha acesso a sua rede local. Isto inclui as suas visitas que conectam no seu wireless. Por padrão, o acesso externo (pela internet) ao samba está bloqueado no firewall. Não recomendaria a abertura deste servidor para a internet e, se for feito, por favor, não usem acesso de convidados.

Para colocar o servidor de arquivos em uso, habilite o serviço e inicie:
/etc/init.d/samba enable
/etc/init.d/samba start
E teste a partir de um computador. No windows, o caminho será \\<nome ou ip do roteador\<compartilhamento> e nas interfaces gráficas do Linux, em geral, smb://<nome ou ip do roteador/<compartilhamento>. Ex:
  • \\roteador\fotos ou smb://roteador/fotos
  • \\192.168.1.1\documentos ou smb://192.168.1.1/documentos
Se seu desejo é o uso somente com usuário convidado, sem senha, este artigo termina aqui para você. Para os mais preocupados com segurança, pode-se criar contas no OpenWRT para cada usuário. O processo é o mesmo de um sistema Linux. Infelizmente, por padrão, não tem os comandos para facilitar esta tarefa. Portanto, para criar usuários, adicione linhas como esta ao arquivo /etc/passwd:
newuser:*:1000:65534:new user name:/var:/bin/false
O newuser é o login do usuário. O número 1000 é o identificador. Deve ser único entre os usuários e preferencialmente acima de 1000. "new user name" é o nome completo, sem muito uso no OpenWRT. "/var" é o home e "/bin/false" o shell. Se ele não for conectar por SSH com este usuário no roteador, pode ficar como está. O caminho do home, "/var", pode ser interessante mudar se for habilitada a opção "homes" ou "compartilhas os homes dos usuários" na configuração do samba. Assim, quando ele se autenticar, será criado dinamicamente um diretório compartilhado com o nome do usuário para este caminho. É necessário definir uma senha para este usuário no samba utilizando o comando smbpasswd. Na primeira vez, é preciso criar o usuário nos bancos de dados do samba.
smbpasswd -a usuário
O mesmo comando pode ser usado para trocar a senha, mas sem o "-a".

Com isto temos mais uma função, um NAS, consolidado no roteador. Com um NAS e um servidor DLNA, você terá um MediaBox. Com o NAS e um cliente Torrent, um SeedBox. E por que não ambos? E por que não mais coisas? Isto fica para outro post. Até mais.

domingo, 31 de março de 2013

OpenWRT: Expandindo o espaço do disco com unidade externa

O grande limitador de um roteador com OpenWRT não está no software que ele usa. Afinal de contas, rodando um Linux, é possível montar um servidor completo. O que restringe os usos do roteador são suas características fisicas, principalmente disco e memória. Processador também é um limitador importante para operações de tempo real, como streaming de conteúdo multimídia, mas pouco podemos fazer para melhorar o processador. Ao menos para o disco e a memória temos alguma alternativa. Sim, também é possível trocar os chips da placa por outros de maior capacidade, mas o que eu vou mostrar aqui é algo bem menos intrusivo.

Como já escrevi anteriormente, em imagens squashfs, OpenWRT divide o sistema de arquivos em duas partes: uma imagem base e as suas alterações. A primeira, chamada de "rom", é um sistema de arquivos completo, imutável, e somente é modificado na gravação de uma nova firmware. O usuário nem nota esta característica pois qualquer alteração efetuada nesta imagem são guardados em uma segunda área de disco, o chamado "overlay". O espaço livre do disco é, na verdade, o espaço disponível na "overlay". Seguindo esta estrutura, não adianta apagar coisas do disco que sejam provenientes da "rom" pois eles somente serão marcados como apagados e não serão liberados do disco.

Por padrão, o "kernel" e a "rom" dividem a flash do roteador e o que sobra fica para a "overlay". Quanto maior as duas primeiras, menos espaço "livre", e tudo isto em uma flash de 4 ou 8MB. O que vamos fazer é configurar o OpenWRT para usar uma unidade externa como a "overlay", expandindo o limite disponível.

O primeiro passo é escolher a unidade externa. No meu caso vai ser um pendrive antigo de 128MB, mas pode ser qualquer dispositivo de armazenamento USB. A configuração inicial é a mesma apresentada no último post. Se conectar o dispositivo e ele aparecer em /mnt ou no comando mount, você está pronto para a segunda etapa.

É bom ter uma configuração funcional antes de iniciar o processo. Caso você remova o disco externo, você terá seu roteador com esta configuração. Sugiro algo simples com a capacidade de acessar a internet.

A montagem automática funciona muito bem para dispositivos de uso eventual. Porém, como será um dispositivo permanente, o ideal é fixar algumas configurações. A primeira coisa a ser melhorada é o ponto de montagem. "/dev/sda5" não diz muito a quem está lendo e quando se trata de discos, é importante não errar a unidade. Também, se for conectada mais de uma unidade, a ordem que estes discos aparecem dependem da ordem de conexão. O primeiro será o sda, o segundo sdb e assim por diante. O ideal é a ordem dos discos não influencie. Para estas configurações, existe o arquivo "/etc/config/fstab". A entrada que nos interessa é a de montagem. Você pode ter quantas entradas destas desejar. No meu caso, terei 2: uma para a partição do HD externo e outra para a nova "overlay".

Atualizado em 2015-09-30: para versões mais novas (como a CC), o recomendado é gerar a configuração "/etc/config/fstab" com:

# block detect >/etc/config/fstab

Depois é só ajustar os valores (normalmente só o enable)

Existem três características que podem ser usadas para identificar um disco no OpenWRT (também suportadas em Linux "convencionais"): dispositivo, nome e uuid. O primeiro é o nome do arquivo que representa o dispositivo, em geral /dev/sd??. Como já comentei, este nome depende da ordem de conexão dos discos e deve ser evitado. A segunda forma, pelo nome, usa o nome ou rótulo dado ao sistema de arquivos, configurado na formatação ou posteriormente. Para partições ext2/3/4, o comando é o tune2fs. O terceiro é o uuid. Ele funciona como um identificador único e é gerado na criação do disco (tune2fs também pode alterá-lo). Se gerado aleatoriamente, é desprezível a possibilidade de conflito. Apesar da segurança do uuid, prefiro a contextualização que o nome me fornece. Estas propriedades dos discos podem ser visualizadas com o comando "blkid". Como usarei dois discos, foram adicionadas as seguintes linhas no meu arquivo /etc/config/fstab:
config mount
        option target   /mnt/usb-dados
        #option device  /dev/sda1
        option label    "usb-dados"
        #option uuid    "b7dc2020-b12a-431e-98d3-619a..."
        option fstype   ext4
        option options  rw,sync
        option enabled  1
        option enabled_fsck 0
config mount
        option target /mnt/extroot
        option label "openwrt-extroot"
        option fstype ext3
        option options rw,sync
        option enabled 1
        option enabled_fsck 0
Para registro, deixei intencionalmente as opções para apontamento por dispositivo e uuid. Porém, estas opções, por estarem comentadas, não serão lidas. Reiniciando o serviço fstab ou o roteador, você terá o disco identificado como usb-dados montado em /mnt/usb-dados e o nomeado "openwrt-extroot" em /mnt/extroot. O caminho deste segundo é temporário e logo será substituído.

Se as partições retornarem de um reboot montadas, é hora de migrar da "overlay" interna para a externa. O primeiro passo é configurar em  /etc/config/fstab a nova partição como a "overlay". E isto depende da versão que você está usando do OpenWRT. Para a versão 12.09, ainda em desenvolvimento, basta trocar onde antes era "/mnt/extroot", colocar "/overlay". Para a versão 10.04.1, backfire, é necessário instalar o pacote "block-extroot" adicionar a opção "option is_rootfs 1" e não alterar a opção target para "/overlay".

Agora basta popular a nova partição Copie os arquivos da "overlay" atual para a nova:
tar -C /overlay -cvf - . | tar -C /mnt/extroot -xf -
Lembre-se de ajustar o nome em negrito para o ponto de montagem em uso pela futura "overlay". Mas preciso usar o tar? É bom pois ele copia todos os atributos necessários e não sei se o cp do busybox faria melhor.

Se tudo der certo, só falta reiniciar. Antes, minhas montagem antes de reiniciar eram estas:
# mount
rootfs on / type rootfs (rw)
/dev/root on /rom type squashfs (ro,relatime)
proc on /proc type proc (rw,noatime)
sysfs on /sys type sysfs (rw,noatime)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noatime,size=30856k)
tmpfs on /dev type tmpfs (rw,noatime,size=512k,mode=755)
devpts on /dev/pts type devpts (rw,noatime,mode=600)
/dev/mtdblock3 on /overlay type jffs2 (rw,noatime)
overlayfs:/overlay on / type overlayfs (rw,relatime,lowerdir=/,upperdir=/overlay)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
none on /proc/bus/usb type usbfs (rw,relatime)
/dev/sda5 on /mnt/usb-dados type ext4 (rw,sync,relatime,user_xattr,barrier=1,data=ordered)
/dev/sdb1 on /mnt/extroot type ext3 (rw,sync,relatime,user_xattr,barrier=1,nodelalloc,data=ordered)
E com a nova "overlay" ficaram:
/dev/root on /rom type squashfs (ro,relatime)
proc on /proc type proc (rw,noatime)
sysfs on /sys type sysfs (rw,noatime)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noatime,size=30856k)
tmpfs on /dev type tmpfs (rw,noatime,size=512k,mode=755)
devpts on /dev/pts type devpts (rw,noatime,mode=600)
/dev/sdb1 on /overlay type ext3 (rw,sync,relatime,user_xattr,barrier=1,nodelalloc,data=ordered)
overlayfs:/overlay on / type overlayfs (rw,relatime,lowerdir=/,upperdir=/overlay)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
/dev/sda5 on /mnt/usb-dados type ext4 (rw,sync,relatime,user_xattr,barrier=1,data=ordered)
none on /proc/bus/usb type usbfs (rw,relatime)
E, principalmente, o espaço livre:
# df -h
Filesystem                Size      Used Available Use% Mounted on
rootfs                  117.6M     13.7M     97.8M  12% /
(...)
Pronto! É espaço de sobra para instalar o que eu pretendo utilizar no roteador. Apesar de ser apenas 128MB, é muito mais do que os 6MB restantes da flash interna. Nos próximos posts, farei a configuração do samba, servidor de impressão e cliente torrent. Até mais e Feliz Páscoa.

segunda-feira, 14 de janeiro de 2013

OpenWRT: conectando um HD pela USB

De volta da vida desconectada, vou começar a escrever as possibilidades de ter um roteador com uma porta USB. Como será um requisito para qualquer uso mais intenso do roteador, precisamos de mais espaço em disco. Isto pode ser obtido conectando qualquer dispositivo de armazenamento USB na porta USB do roteador como Pendrive, HD Externo, leitor de  cartão de memória, celulares, etc. No meu caso, vou conectar um HD externo de 1TB.

Diferentemente de um Linux para Desktop, o OpenWRT precisa economizar espaço em disco ao extremo. Uma das formas de ganhar alguns "mega" é filtrar os módulos de kernel instalados. Em geral, para equipamentos com USB, é pré-instalado um módulo básico de suporte USB como o kmod-usb2. Porém, estes módulos básicos não incluem o uso de unidades de armazenamento USB. O que você vai inicialmente precisar são os pacotes:

  • kmod-usb-storage
  • kmod-usb-storage-extras (opcional, para unidades alternativas como leitores de cartão)
  • para OpenWRT 10.03.1
    • block-hotplug
    • block-mount
  • para OpenWRT 12.09-rc1 (usado nos testes)
    • block-mount (agrega o block-hotplug e o block-extroot)

E os respectivos módulos para cada sistema de arquivos que você pretenda usar:

  • kmod-fs-ext4: para ext2, ext3 e ext4
  • kmod-fs-vfat: para FAT (em geral o que você encontrará em pendrives)
  • kmod-fs-ntfs: NTFS usado pelo windows mas sem acesso de escrita. 

Existem outras alternativas (busque por pacotes kmod-fs-*), mas o que você vai precisar em 99% dos casos são estes três. Se a ideia é deixar um disco fixo no roteador, recomendo usar o ext4. É rápido e feito para ser usado no Linux. Se for movimentar esporadicamente o roteador, ainda assim recomendaria o ext4. Existe driver para windows que funciona muito bem. Também é possível usar o ntfs-3g para montar NTFS com escrita no roteador. Você terá um desempenho inferior e precisará de mais espaço no roteador para instalar os drivers e programas necessários.

Ainda sobre o vfat, e provavelmente o ntfs, você precisará de mais um módulo de suporte da língua do sistema de arquivos. Ao tentar montar o disco, aparecerá uma mensagem de erro do kernel como esta:
FAT: IO charset iso8859-1 not found
Isto significa que você não tem o driver do NLS (Native Language Support) usado pelo seu sistema de arquivos. Instale o correspondente pacote kmod-nls-xxx, onde xxx será a codificação necessária, como kmod-nls-iso8859-1. Com ext4, você não teria este problema.

O que eu uso nas minhas unidades de armazenamento maiores é dividir o disco em duas ou mais partições, sendo uma pequena em FAT e as demais em EXT4. A partição FAT é usada para guardar o driver do ext para windows, para ser instalado em novas máquinas, e para trocas de arquivos com dispositivos não muito abertos como impressoras, TV. As partições EXT4 guardam os dados de verdade.

Com os pacotes instalados, conecte seu HD externo. Deverá aparecer algo similar nas mensagens de kernel (dmesg)
[864448.690000] usb 1-1: new high-speed USB device number 2 using ehci-platform
[864448.840000] scsi0 : usb-storage 1-1:1.0
[864449.850000] scsi 0:0:0:0: Direct-Access     WD       My Book 1110     1030 PQ: 0 ANSI: 4
[864449.860000] scsi 0:0:0:1: CD-ROM            WD       Virtual CD 1110  1030 PQ: 0 ANSI: 4
[864449.880000] scsi 0:0:0:2: Enclosure         WD       SES Device       1030 PQ: 0 ANSI: 4
[864449.890000] sd 0:0:0:0: [sda] 2928904192 512-byte logical blocks: (1.49 TB/1.36 TiB)
[864449.900000] sd 0:0:0:0: [sda] Write Protect is off
[864449.910000] sd 0:0:0:0: [sda] Mode Sense: 23 00 10 00
[864449.920000] sd 0:0:0:0: [sda] No Caching mode page present
[864449.920000] sd 0:0:0:0: [sda] Assuming drive cache: write through
[864449.940000] sd 0:0:0:0: [sda] No Caching mode page present
[864449.940000] sd 0:0:0:0: [sda] Assuming drive cache: write through
[864449.990000]  sda: sda1 sda2 < sda5 >
[864449.990000] sda: partition table partially beyond EOD, enabling native capacity
[864450.000000] sd 0:0:0:0: [sda] No Caching mode page present
[864450.010000] sd 0:0:0:0: [sda] Assuming drive cache: write through
[864450.020000]  sda: sda1 sda2 < sda5 >
[864450.020000] sda: partition table partially beyond EOD, truncated
[864450.060000] sd 0:0:0:0: [sda] No Caching mode page present
[864450.070000] sd 0:0:0:0: [sda] Assuming drive cache: write through
[864450.070000] sd 0:0:0:0: [sda] Attached SCSI disk
No meu caso, sda1 é uma partição FAT, sda2 uma extended que contém a partição sda5. Magicamente, o disco foi montado. O comando mount mostra a localização:
root@router:~# mount
(...)
/dev/sda5 on /mnt/sda5 type ext4 (rw,relatime,user_xattr,barrier=1,data=ordered)
O próprio OpenWRT montou o disco em /mnt/sda5. Só acessar o diretório e todo o conteúdo estará disponível.

Para HD, é bom desligá-los quando eles não forem necessários. Isto poupará suas partes móveis e aumentará a vida útil da unidade. O pacote luci-app-hd-idle realiza esta tarefa. A sua configuração é feita pela interface Web (luci) e é bem intuitivo. Basicamente, configura-se a unidade e o tempo sem atividade até que o disco seja desligado. Se alguma informação for necessária após ele ser desligado, o primeiro acesso apenas levará alguns segundos a mais do que o normal até o disco voltar a girar.

Até este ponto, a unidade estará somente "visível" para o roteador. Já é possível copiar arquivos de e para o roteador usando programas como o scp e o winscp mas nada muito amigável. O próximo passo será a instalação de um serviço de compartilhamento de arquivos (samba).

Até a próxima.

sexta-feira, 21 de dezembro de 2012

OpenWRT: Instalação básica com vídeo

A pedidos, fiz um primeiro vídeo mostrando uma ideia de como ocorre a instalação de um OpenWRT, as perguntas que precisam ser respondidas durante o processo e uma configuração básica da rede sem fio.

Não é direcionado para usuários que já usam o OpenWRT.


O audio ficou um pouco ruim mais para o final porque movimentei o microfone. Na próxima vez prometo que vai ficar melhor.

Os próximos artigos serão mais interessantes, relativos a problemas que vou resolver aqui em casa:

  • Usando o roteador como servidor de armazenamento com samba e um HD USB;
  • Usando o roteador como um media server;
  • Usando o roteador para baixar torrents;
  • Testes com a nova versão do multiwan mwan3 (a pedidos);
  • Portal de autenticação para usuários (a pedidos);
Estarei "offline" nas próximas semanas e devo escrever sobre estes assuntos mais para o final de janeiro.

Até a próxima. Feliz Natal e Bom Ano Novo!

PS: O mundo realmente não acabou?

terça-feira, 20 de novembro de 2012

OpenWRT: Problemas com o TP-Link TL-MR3420

Mais de duas pessoas entraram em contato comigo para tentar resolver problemas com o roteador TL-MR3420 da TP-Link. O que sempre recomendo é entrar no modo de recuperação. Para quem utiliza firmwares do tipo squashfs, este recurso é uma bênção. Porém, por alguma razão antes desconhecida por mim, nenhum deles conseguiu ativar o modo de recuperação. Uma vez, culpe o usuário. Duas, o desenvolvedor.

Investigando um pouco melhor, entrei no artigo da wiki do OpenWRT sobre este roteador. E encontrei este aviso logo na abertura:
The failsafe function is not working at launch time, serial is also unfriendly: Stick to trunk. More...
Isto referenciando a versão backfire 10.03.1, a última estável e que a maioria usa. Bem, isto quer dizer que quem possui qualquer versão atualmente estável do OpenWRT neste roteador não poderá utilizar o modo de recuperação.

A correção ocorreu neste patch, mas isto foi tarde demais para a versão lançada. Basicamente, o problema ocorreu com o nome dos botões "Reset" e "QSS". Por não achar os botões no processo de iniciação do roteador, eles não podem ser utilizados para acionar o modo de recuperação.
Sempre é importante ler a documentação do seu modelo na wiki do OpenWRT. Cada modelo possui suas peculiaridades e é importante conhecer os pontos fracos e problemas de compatibilidade com o seu roteador antes de instalar o OpenWRT pela primeira vez.
Bem, o que eu posso fazer, então? Depende da sua situação.

Se ainda está pensando em usar o OpenWRT para este roteador, sugiro que espere o lançamento da versão "12.09", que já está em beta2. Logo teremos uma versão estável.

Se estiver já com o OpenWRT funcionando e em uma versão 10.03.1 ou inferior, procure não alterar configurações críticas como firewall, interfaces de rede, VLAN, até o lançamento e atualização da nova versão.

Para os mais corajoso (ou malucos como eu), você também pode ajudar a melhorar a próxima versão do OpenWRT. Instale agora mesmo a versão beta2 e ajude a encontrar os bugs. Ao menos o "modo de recuperação" deve funcionar sem problemas.

Caso você já esteja na situação onde o roteador não está funcionando por algum problema de configuração, resta apenas a alternativa da recuperação pela serial. Com a serial, você poderá interagir com o seu roteador assim como já fazia com uma conexão SSH. Isto é suficiente para recuperar casos pontuais como problemas na configuração de rede ou firewall. Se ainda funciona os comando básicos, você pode também solicitar que todas as configurações sejam apagadas.

Caso o problema seja mais grave, como ter apagado metade dos arquivos, também é possível acionar o "modo de recuperação" por comandos na serial. É o mesmo mecanismo que funcionaria com os botões se estes estivesse configurados corretamente. As mensagens durante o boot vistas pela serial indicarão o momento para se manisfestar e ativar o modo de recuperação.

Os modelos TL-MR3420 com problema já devem estar funcionando com os procedimentos anteriores. Porém, com a serial funcionado, vale a pena citar mais uma funcionalidade. Em casos mais extremos, é possível gravar uma nova imagem interagindo diretamente com o gerenciador de boot (UBoot). Enviando comandos pela serial, podemos solicitar ao roteador que carregue uma nova imagem pela rede (via TFTP) e grave na memória. Mesmo se não possuir rede, é possível enviar a firmware pela serial pelo protocolo kermit (já fiz e realmente funciona). Neste caso, o processo é mais demorado do que o TFTP mas pode ser necessário se seu computador não possui uma interface Ethernet cabeada.

Alguns roteadores, não os modelos da TP-Link, já estão configurados para mais uma forma de recuperação mais "simples", em especial para a situação de firmwares defeituosos gravados. "simples" por não precisar de uma serial mas as vezes mais complicada por envolver tempos definidos e configurações de rede rígidas. Nestes roteadores, o gerenciador de boot aguarda o envio da firmware, por TFTP, em um espaço curto de tempo durante a iniciação. Se receber, gravam no roteador. Se não, seguem normalmente o processo. Contudo, novamente, tudo isto depende de cada roteador.

Boa sorte aos colegas com problemas e tentarei ajudar no que eu puder para recuperá-los. Só garanto uma coisa: depois de recuperar o roteador usando a serial, você não terá mais medo de alterar qualquer coisa no roteador e de gravar qualquer firmware.

segunda-feira, 15 de outubro de 2012

Transformando partições para RAID1

Armazenamento é uma questão crítica para grande partes dos serviços. Uma das falhas comuns no armazenamento de dados em computadores é a falha nos dispositivos de armazenamento, principalmente quando se trata de um disco com partes móveis. Uma técnica clássica de mitigar este tipo de problema é a utilização de RAID (Redundant Array of Inexpensive Drives).

Existem diversas combinações de arranjo de discos, RAID1, RAID5, RAID6, e combinações, que buscam manter a integridade dos dados mesmo na eventual falha de discos. Neste artigo, não vou entrar em detalhes sobre cada uma das técnicas, apenas dizer que o RAID1 (mirroring), espelha todos os dados em ambos os discos.

Para pobres mortais que não possuem o suporte a RAID em Hardware, a solução é utilizar os recursos do Linux para prover a segurança. Basicamente será utilizado apenas o comando mdadm, responsável por toda a gerência de RAID em software no Linux. Neste artigo, vou mostrar como montar um RAID1 a partir de uma partição com dados, sem a necessidade de copiar os dados de um lado para outro.

O mdadm cria um dispositivo MD que agrupa os diversos discos. Por exemplo, ao juntar as partições sda3 e sdb4 em um RAID1, você terá um md0 com um tamanho igual ao menor dos discos (na verdade, ligeiramente menor do que isto, mas vemos isto mais adiante):
mdadm --create /dev/md0 --level 1 /dev/sda3 /dev/sdb4
Você não mais irá acessar os dados em sda3 ou sdb4, apenas em md0. O dispositivo md0 pode ser usado como uma partição/disco normal, criando sistema de arquivos e montando para uso.

O mdadm assume que ambas as partições não possuem dados importantes e, portanto, nada precisa ser mantido. No meu caso, quero manter os dados em um dos discos.

O primeiro passo para entender a gamb...técnica é compreender como são mantidos os metadados do disco RAID. Os metadados armazenam informações como data da última alteração no disco, dispositivos participantes. No Linux, este metadado pode ser volátil,  e portanto, perdido a cada parada, ou embutido na partição/disco do RAID em um superblock.

Quando os metadados são voláteis, cada disco terá, bit a bit, os mesmos dados mostrados. No exemplo anterior, todos os bits em /dev/md0 estarão na mesma sequência que em /dev/sda3  e /dev/sdb4. Isto traz alguns problemas como a possibilidade de montar inadvertidamente um dos discos e corromper os dados. Não existe qualquer controle de alteração, ficando a cargo do administrador proteger os dados quanto a alterações fora do RAID. Também, para RAID com diversos discos, caso o arquivo de configuração seja perdido, será uma tarefa possivelmente complicada identificar o papel de cada disco no RAID (exceto para o RAID1 onde todos armazenam a mesma função).

A solução mais indicada segura para armazenar os metadados é mantê-los em um superblock embutido na partição/disco. Existem atualmente 4 formatos deste superblock:
  1. versão 0.90
  2. versão 1.0
  3. versão 1.1
  4. versão 1.2
A primeira versão, 0.90 está em desuso e é indicada apenas para casos especiais onde o gerenciador de boot não reconhece os novos formatos (grub2 trabalha com LVM e RAID sem problemas). Esta versão também possui outros limitadores como o tamanho máximo do disco e o número de dispositivos. Em geral, as versões mais novas são mais indicadas.

A versão padrão em ambientes atualizados é a 1.2. A diferença entre as versões 1.x está basicamente na posição do disco onde este metadado será armazenado. A primeira, 1.0 fica no final do disco/partição. A versão 1.1 logo no início do disco/partição e a versão fica 4k de distância do início do disco.

Voltamos ao problema em questão de transformar um disco não RAID para RAID1. A posição onde ficará o metadado possui dados do sistema de arquivos. Precisamos liberar estes blocos antes da criação do RAID. Para as versões 1.1 e 1.2, isto seria no começo do disco. Porém, seria necessário liberar um pedaço no final do disco e deslocar todos os dados para poder utilizar o começo do disco. O mais simples seria utilizar a versão 1.0 e liberar a porção final do disco. Felizmente, isto não é um problema no Linux. Os sistemas de arquivos podem ser redimensionados com simples comandos.

Inicialmente temos a seguinte situação:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |               ext3                  |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|                                                   |
+---------------------------------------------------+

O disco sda possui duas partições, ambas com sistema de arquivos ext3 e ocupando todo o espaço da partição. O disco sdb não possui qualquer partição. Vamos primeiro liberar o espaço para o metadado na partição sda2. O metadados é pequeno mas, por garantia, pode ser liberado umas dezenas de megabytes do sistema de arquivos. No pior dos casos, libere todo o espaço disponível. Ao final do processo, este espaço será recuperado. Para saber quanto é o mínimo, tente reduzir o tamanho para 1 bloco. Ex:
# resize2fs /dev/sda2 1
resize2fs 1.41.9 (22-Aug-2009)
resize2fs: New size smaller than minimum (54176)
Na sequência, escolha um valor mais apropriado, maior ou igual ao mínimo. Ex:
# resize2fs /dev/sda2 54180
O comando provavelmente solicitará a execução do fsck antes do processo. Ao final do processo, teremos:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |        ext3    :         livre      |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|                      livre                        |
+---------------------------------------------------+

É importante lembrar que a partição continua com o mesmo tamanho. Apenas o sistema de arquivos foi reduzido. 
Nota: Para os antigos usuários do Partition Magic, ele fazia as duas tarefas: reduzia o sistema de arquivos e a partição. 
Agora, criamos o RAID1. Iremos utilizar o metadado 1.0, que ocupará a parte do espaço livre liberado no passo anterior:
# mdadm --create /dev/md0 --metadata 1.0 --level=1 --raid-devices=2 /dev/sda2 missing
Ele alertará que existe um sistema de arquivos nesta partição. Ignore o aviso. Após este passo, você já terá o dispositivo RAID pronto, mas com apenas um disco. O "missing" no comando anterior informou que um dos discos está ausente. Você pode ver a situação de seu dispositivo em /proc/mdstat:
# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 sda2[0]
      208884 blocks super 1.0 [2/1] [U_]
           
unused devices: <none>
O símbolo "_" em "[U_]" indica que apenas um dos dois dispositivos deste RAID estão em operação/presentes.

E o disco ficou desta forma:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |     ext3       : livre  :  metadado |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|                      livre                        |
+---------------------------------------------------+

Agora o espaço livre após o sistema de arquivos e antes do metadado pode ser recuperado. Porém, isto deve ser feito já no disco RAID e nunca no dispositivo original sda2! Basta reexecutar o resize2fs sem definir o tamanho para ele ocupar todo o espaço disponível:
# resize2fs /dev/md0
E o disco ficará:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |           ext3          :  metadado |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|                      livre                        |
+---------------------------------------------------+


Para completar o RAID1, basta adicionar as partições/discos espelhos:
mdadm --manage /dev/md0 --add /dev/sdb
OBS: Coloquei intencionalmente um disco inteiro como exemplo que é possível combinar partições e discos mas também seria possível particionar o disco sdb e utilizar uma de suas partições para o comando anterior:
Neste ponto, o disco já estará em processo de sincronia. Acompanhe pelo arquivo /proc/mdstat. Sugiro utilizar o comando watch:
watch cat /proc/mdstat
O layout final ficará:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |           ext3          :  metadado |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|           ext3          :  metadado :    livre    |
+---------------------------------------------------+

O espaço livre ao final de sdb é devido ao fato de que sdb é maior do que a partição sda2. Se este for seu caso, o disco sdb poderia ser dividido em partições, sendo uma do tamanho exato da sda2. Assim, o restante do disco poderia ser utilizado para outras partições com dados diversos.

Seu disco está pronto para uso. Se o sda2 estava em uso, lembre de retirar qualquer configuração de montagem deste disco (em /etc/fstab) antes de reiniciar o computador. Porém, é possível que este RAID não seja "ligado" automaticamente quando o sistema for reiniciado.

Em algumas distribuições, todos os RAID encontrados serão ligados. Porém, em outros casos, por cautela dos desenvolvedores, é necessário explicitamente indicar o que o administrador deseja. Isto depende de cada distribuição. Para OpenSUSE/SLES, crie o arquivo /etc/mdadm.conf, se não existir, e inclua uma linha como esta:
ARRAY /dev/md0 UUID=2de1a56d:717ce2cc:231893bb:4e44f123
O UUID é diferente para cada RAID e pode ser encontrado executando o comando:
mdadm --detail /dev/md0
Ative o serviço boot.md (provavelmente outro nome em outras distribuições):
chkconfig boot.md on
Reinicie o sistema para testar sua configuração.


Em sistemas modernos, a montagem direta de dispositivos que formam o RAID (como a sda2 e sdb) irá falhar por causa das verificações de proteção do sistema de arquivos.

Caso seja necessário retornar ao estado original:
  1. Remova a configuração do disco no /etc/fstab e no /etc/mdadm.conf
  2. Pare o RAID: mdadm --stop /dev/md0
  3. Zere os metadados: mdadm --misc --zero-superblock /dev/sda2
    1. Isto para cada dispositivo que participava do RAID
  4. Recupere o espaço usado pelo superblock
    1. resize2fs /dev/sda2
Happy hacking!

terça-feira, 3 de julho de 2012

Instalação de Linux (antigo) em discos GPT

Nos percalços da administração de sistemas, encontrei um problema interessante para resolver. Precisava instalar um RHEL 5.8 em um servidor com 6 discos de 600MB em RAID 5.  Fácil? Nem tanto. Vamos aos problemas.

Em uma configuração de RAID 5, um dos discos é usado para paridade. Neste caso, temos 5x600MB ou 3TB de espaço líquido. Como o RAID é implementado por uma controladora, o processo é mais simples. Tudo é apresentado transparentemente para o sistema operacional como um disco único de 3TB. Porém, justamente este é o problema.

Normalmente é utilizado nos discos uma tabela de partição no formato DOS, aquela com MBR, 4 partições primárias, partições estendidas. Contudo, este formato desenvolvido na época dos Megabytes não lida muito bem com o mundo dos Terabytes. O tamanho máximo representável de disco é de 2.2 TB. No meu caso, tenho 3 TB. E agora José? A solução curta e grossa é dividir os discos em 2 RAID 5, cada um com 3 discos. Porém, neste caso, eu perderia 2 discos e não 1 com paridade. Como sempre, alguém já encontrou uma solução: um novo formato de partições chamado de "GUID Partition Table", ou para os mais íntimos, GPT.

O formato GPT faz parte do padrão (U)EFI que busca substituir a BIOS hoje presente na maioria dos computadores. Os servidores e sistemas operacionais mais novos suportam estes padrão. Bem, ai chegamos a outro problema. O RedHat Enterprise Linux (RHEL) versão 5.8 não suporta UEFI para ambientes x86. Se fosse na versão 6, o suporte é nativo. Como isto é um requisito do projeto, preciso resolver ainda com o RHEL v5.8.

O primeiro passo foi investigar o que cada componente deste ambiente suporta que recurso. Cheguei a este resultado:
  • Servidor:
    • Suporta BIOS e UEFI
    • Suporta GPT tanto em BIOS como UEFI
Isto já é um ótimo começo. O uso do UEFI não é requisito para a BIOS usar discos GPT. Quanto ao RHEL v5.8:
  • RHEL
    • Grub (gerenciador de BOOT)
      • Suporta somente formato DOS
    • Kernel
      • Suporta GPT mas não EFI
    • Ferramentas
      • Exceto o fdisk, suportam GPT e DOS
Tanto o grub quanto o kernel não suportam EFI. O grub nem mesmo suporta o GTP. Buscando um denominador comum, podemos utilizar o modo BIOS, disco com GPT mas empacamos no gerenciador de BOOT (obs: grub2 suporta GPT). A BIOS pode ler o gerenciador de BOOT, ele roda mas não encontra seus arquivos. Se conseguisse carregar o kernel e o INITRD, o problema estava resolvido. Precisamos, portanto, de alguma alternativa de BOOT ou alguma bruxaria para fazer o grub funcionar.

A primeira alternativa mais simples é utilizar um disco DOS para armazenar os arquivos do grub. Isto seria o diretório /boot. Nos meus testes, utilizei um pendrive e durante o processo de instalação configurei o /boot para usar o pendrive utilizando o formato DOS. Instalação sem problemas do início ao fim. Sistema iniciou e desligou sem erros. Mas este pendrive não ficou muito interessante... e se alguém retirar o pendrive? Só irei notar a falta dele quando reiniciar o servidor e aí, já é tarde.

Buscando mais alternativas para casos similares, encontrei o caso de máquinas MacBook, que usam UEFI e GPT, e onde era instalado o Windows XP. O GPT, para evitar problemas com softwares particionadores antigos, mantém uma tabela de partição no formato DOS. O primeiro setor do disco possui uma configuração de uma partição que ocupa toda a extensão do disco e do tipo "GPT EFI". O fdisk, que não suporta GPT, mostra esta informação. Note que o primeiro setor usado é o 1 e não o 63 como em discos DOS convencionais.

# fdisk -u -l

WARNING: GPT (GUID Partition Table) detected on 'sda'! The util fdisk doesn't support GPT. Use GNU Parted.                                     
(...)                                                                                            
                                                                                                                                              
Device Boot      Start         End      Blocks   Id  System                                                                                  
  sda1               1  4294967295  2147483647+  ee  GPT  
O grub, e outros que não suportam GPT, também busca a informação onde estaria a MBR de um disco em formato DOS. A solução é (ab)usar desta configuração para informar ao grub onde ele poderia encontrar a partição /boot e seus respectivos arquivos. Isto é chamado de MBR híbrida, por conter informações do GPT e os dados de algumas partições ainda em formato DOS.

Agora, é necessário editar a tabela de partição da MBR e colocar as informações necessárias. Tentei utilizar o fdisk mas ele acabou destruindo todas as partições GPT, que tive que caçar bits para recriá-las. Googlando mais um pouco, encontrei o projeto GPT fdisk. Este projeto busca implementar um fdisk para formato GPT e algumas funcionalidades como a construção de uma MBR híbrida. Vamos ao roteiro completo.

Roteiro de instalação para o uso de MBR híbrida

Estas são instruções para o RHEL mas que, com pequenas adaptações, podem ser aproveitadas em outros ambientes.

Como primeiro passo, insira uma unidade de armazenamento temporária no servidor e dispare a instalação normalmente. Durante a fase de formatação de discos, vá para o terminal (CTRL+ALT+F2) e crie a tabela de partição em formato GPT:

# parted
(parted) mktable
... yes
... gpt
(parted) quit

Retorne ao instalador gráfico (CTRL+ALT+F6). Opte por um particionamento personalizado e utilize a seguinte disposição:

Dica: marque a partição PAD como "forçada como primária" para que ela fique como a primeira.
Atenção: a ordem é importante!
  • sda (GPT) - disco RAID 5
    1. partição ext3 PAD (2 MB) (não montada ou em diretório não usado como /pad)
    2. partição ext3 para o /boot2 (que se tornará /boot)
    3. PV LVM
      1. partição ext3 para /
      2. partição swap
      3. (demais partições...)

  • sdb (DOS) - pendrive

    1. partição ext3 para /boot
Siga a instalação normalmente. O gerenciador de BOOT deve ser instalado no disco sda, que é a opção padrão. A função da partição PAD irei explicar mais adiante.

O arranjo final dos discos fica desta forma:

# fdisk -u -l

Device Boot      Start         End      Blocks   Id  System                                                                                  
  sda1               1  4294967295  2147483647+  ee  GPT 

# parted
(parted) unit s
(parted) print

Model: DELL PERC H700 (scsi)
Disk /dev/sda: 5854986239s
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start     End          Size         File system  Name  Sinalizador
 1      32s       4129s        4067s        ext2         ext3
 2      4130s     1028129s     1024000s     ext3         ext3
 3      1028130s  5854986206s  5853958077s               lvm
O instalador não configura corretamente o boot no pendrive. Reinicie novamente usando a mídia de instalação da máquina. Porém, ainda no gerenciador de boot do DVD, entre no modo de recuperação: "linux rescue". No modo de recuperação, ele oferecerá a possibilidade de montar o sistema instalado. Permita a montagem. No shell, execute:

# chroot /mnt/sysiimage/
# grub-install --recheck /dev/sda
# exit
# reboot

Agora, o sistema deverá iniciar normalmente. Efetue os passos finais da instalação.
 
Se a presença perpétua da unidade de armazenamento "temporária" não é um problema para o seu caso, você pode parar neste ponto. Neste caso, as partições sda1 e sda2 também não seriam necessárias. Para os demais casos, vamos a etapa retirar a dependência desta unidade de arO instalador não considera o boot no pendrive. Reinicie mazenamento temporária.

No sistema, instale o programa gdisk.
# wget http://apt.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS/gdisk-0.6.10-1.el5.rf.x86_64.rpm
# rpm -i gdisk-0.6.10-1.el5.rf.x86_64.rpm
Agora precisamos criar a configuração híbrida:
# gdisk /dev/sda
... r
... h
... 2
... Y
... 83
... N
... N
... w
Normalmente seria interessante criar uma partição para ocupar todo o restante do disco (última pergunta, penúltimo comando). Porém, por algum BUG deste programa, ele entra em uma live lock, provavelmente por causa do disco com tamanho maior que o limite da MBR. Só não alternar novamente as partições que tudo ficará bem. 


É possível que a partição /pad seja corrompida neste processo. Qualquer coisa, recrie o sistema de arquivos do /pad
# mkfs.ext3 /dev/sda1 -L /pad
O disco, quando observado pelo fdisk fica desta forma:
Disk /dev/sda: 2997.7 GB, 2997752954880 bytes
255 heads, 63 sectors/track, 364456 cylinders, total 5854986240 sectors
Units = setores of 1 * 512 = 512 bytes

Dispositivo Boot      Start         End      Blocks   Id  System
/dev/sda1               1        4129        2064+  ee  EFI GPT
Partition 1 does not end on cylinder boundary.
/dev/sda2            4130     1028129      512000   83  Linux
Partition 2 does not end on cylinder boundary.
Note que o início e o fim da partição sda2, como esperado, é o mesmo do apresentado pelo parted. Agora voltamos a questão em aberto da partição PAD. A partição de PAD possui duas funções. A primeira é manter o número dos dispositivos sincronizados entre a GPT e a DOS. Como necessariamente teremos uma partição "GPT EFI" como sda1 do formato DOS, a primeira partição possível seria a sda2 que, coincidentemente, é a partição de interesse para o grub. O outro motivo é preventivo. A primeira posição válida para uma partição no GPT é no setor 32 (observe o parted). No caso do formato DOS, a primeira partição começa no setor 63. Desta forma, se algum programa estiver protegendo ou validando os setores "de controle" abaixo de 63, como o fdisk faz, eles não acessariam o começo de uma partição no setor 34.

Agora basta realizar a migração dos dados e configurações de /boot para /boot2.
  1. Edite o /boot/grub/menu.lst e troque todas as referências de "hd1,0" (sdb1) para "hd0,1" (sda2).
  2. Copie todo o conteúdo de /boot para /boot2 (cp -a /boot/* /boot)
  3. Desmonte ambas as partições (umount /boot /boot2)
  4. Remova a entrada de /boot2 no /etc/fstab. Note que a chamada da partição é pelo LABEL. Para trocar, atualize o label das duas partições:
    1. e2label /dev/sda2 /boot
    2. e2label /dev/sdb1 xxxx
  5. Remonte a partição (mount /boot)
  6. Remova a unidade de armazenamento temporária
  7. Reinstale o gerenciador de boot (grub-install --recheck /dev/sda)
  8. Se tudo ocorrer bem, reinicie o sistema.
Somente para reforçar a ideia, se seu sistema não tem discos de mais de 2.2TB, esqueça tudo que eu escrevi. Se tudo possui suporte nativo ao GPT (BIOS, kernel e gerenciador de boot e ferramentas) não use a MBR híbrida. E, se for necessário, mude para UEFI. Somente em último caso faça o que eu escrevi neste artigo.


Agora, basta cuidar para atualizar os dados da MBR com o gdisk caso seja alterado a posição ou tamanho da partição sda2. Criar ou alterar volumes lógicos não tem problemas.

Até a próxima.