Como alterar configurações de Filesystems exportados via NFS sem reiniciar o serviço

Nesse post vou mostrar como você pode alterar as configurações de um filesystem exportado via NFS, adicionar novos filesystems para exportar, ou removê-los sem ter que reiniciar o serviço do NFS.

Como os caros colegas já devem estar cansados de saber, para exportar filesystems via NFS (vulgo compartilhar diretórios), deve-se criar entradas no arquivo /etc/exports. Cada filesystem exportado deve ser colocado em uma nova linha do arquivo juntamente com as configurações de exportação. Algo como o exemplo abaixo.

[root@linuxserver01 ~]# cat /etc/exports
/bkp/dumps 192.168.0.21(rw,no_root_squash)
/isoimagem *(ro,no_root_squash)
/publico *(rw,no_root_squash)

A questão é que não basta alterar esse arquivo para que as alterações entrem em vigor.
De uma forma geral o processo do NFS Server lê as configurações desse arquivo apenas quando ele é iniciado.
Dessa forma vejo vários colegas reiniciando o serviço NFS para que as alterações sejam efetivadas. O problema disso é que se a alteração ocorrer em servidores de produção esse tipo de ação pode requerer uma janela de manutenção, abertura de uma GMUD, reunião do CAB, e toda a burocracia e demora que estamos acostumados.

A boa notícia é que nem tudo está perdido! 😉
Você pode aplicar as alterações efetuadas no /etc/exports sem reiniciar o NFS Server. Para isso basta usar o comando exportfs!

[root@linuxserver01 ~]# exportfs -r

O parâmetro “-r” informa que você deseja “reexportar” os filesystems listados no arquivo /etc/exports.

Caso você execute o exportfs sem passar nenhum parâmetro, ele listara os filesystems atualmente exportados. Você pode usar o parâmetro “-v” (verbose) para exibir informações mais detalhadas das exportações.

Comparativo entre as versões do SNMP

1. Introdução

Com a evolução dos ambientes de rede, eles se tornaram cada vez mais complexos e difíceis de serem monitorados e gerenciados. Para resolver esse problema, vários pesquisadores buscaram criar soluções que pudessem auxiliar no processo de gerenciamentos de grandes ambientes de rede. Dentre essas soluções destacou-se o SNMP.

O SNMP, desde sua concepção, possui como característica a separação entre as informações trocadas e o protocolo usado para transportar essas informações. Com essa característica, as operações do protocolo não precisam ser definidas de acordo comandos específicos usados para recuperar informações ou alterar as configurações de um dispositivo. Dessa forma, as operações do protocolo são definidas em torno de variáveis chamadas de objects, essas variáveis contêm as informações de gerenciamento.

O resultado dessa separação é um protocolo com complexidade bastante reduzida, pois ao invés de definir dezenas, ou até centenas, de operações quem definem funções específicas de gerenciamento da rede, o protocolo apenas precisa lidar com a transmissão das variáveis objects, sem se importar com o que elas contêm.

2. O SNMP versão 1 (SNMPv1)

O SNMPv1 tem sua origem no protocolo SGMP (Simple Gateway Monitor Protocol) que está definido na RFC 1028. O SGMP foi projetado para ser uma solução intermediária para o gerenciamento de redes enquanto um solução mais abrangente era explorada. No entanto muitos dos conceitos básicos do SNMP atual estão presentes no SGMP.

A primeira definição formal do SNMP ocorreu na RFC 1067 (posteriormente revista nas RFCs 1098 e 1157). Esses documentos descrevem a estrutura das informações de gerenciamento (SMI) (RFC 1155), as bases de informação de gerenciamento (MIB) (RFC 1156) e a estrutura do protocolo propriamente dita (RFC 1157), onde estão descritos os tipos de mensagem, formato das mensagens, protocolos de transporte suportados, entre outras informações.

2.1. As Mensagens

Para um melhor entendimento das mensagens SNMP, é importante ressaltar a diferença entre mensagens SNMP e protocol data units (PDUs). É comum que esses termos sejam usados de forma análoga, isso ocorre porque cada mensagem carrega um PDU, e o PDU é a parte mais importante da mensagem.

No entanto, falando de forma clara, o PDU e a mensagem SNMP não são a mesma coisa. O PDU é a parte da informação que é trocada entre as entidades SNMP (agentes e gerentes). Ele é transportado dentro da mensagem SNMP junto com outros campos de cabeçalho usados para informações de segurança e identificação. Desta forma considera-se, conceitualmente, o formato da mensagem SNMP como tendo duas sessões:

  • Cabeçalho da Mensagem: contém campos usados para controlar a forma como a mensagem é processada, incluindo campos para implementação de segurança;
  • Corpo da Mensagem (PDU): contém a parte principal da mensagem. O corpo da mensagem é o PDU sendo transmitido.
    O cabeçalho da mensagem não requeria muitos campos no SNMPv1, pois o modelo de segurança utilizado, baseado em comunidades, era muito rudimentar. Uma breve descrição da estrutura da mensagem SNMP é mostrada na Tabela 1.
Nome do CampoTipoTamanho (bytes)Descrição
VersionInteiro4Número da Versão: Indica a versão do SNMP da mensagem; usado para assegurar compatibilidade entre versões. Para o SNMPv1, o valor usado é 0, não 1.
ComunityString de octetosVariávelNome da Comunidade: Identifica a comunidade SNMP em que o remetente da mensagem está localizado. Este campo é usado para implementar o mecanismo de segurança baseado em comunidades.
PDUVariávelProtocol Data Unit: O PDU que está sendo transmitido como corpo da mensagem.

Tabela 1: Formato da mensagem SNMPv1

2.1.1. Os Tipos de PDU e seus Formatos

O SNMPv1 define cinco tipos de PDU, são eles: GetRequest, GetNextRequest, GetResponse, SetRequest e Trap.

  • GetRequest: permite ler o valor de uma ou mais instancias de variáveis.
  • GetNextRequest: permite ler o valor de uma ou mais instancias de variáveis sem conhecer o nome exato da mesma.
  • GetResponse: retorna o resultado de uma operação de leitura.
  • SetRequest: permite atribuir o valor de uma variável.
  • Trap: Sinaliza a ocorrência de algum evento. Possui um formato diferente.

Todos os PDUs no SNMPv1 possuem o mesmo formato, com exceção do PDU Trap. A semântica exata de cada campo depende de cada mensagem em particular. Por exemplo, o campo ErrorStatus só tem algum significado quando a mensagem é uma resposta, e não um comando.

A Tabela 2 descreve o formato básico dos PDUs (exceto Trap).

Nome do CampoTipoTamanho (bytes)Descrição
PDU TypeInteiro (Enumeração)4Tipo de PDU: É um valor inteiro que indica o tipo de PDU:Valor do tipo de PDUTipo de PDU0GetRequest1GetNextRequest2GetResponse3SetRequest
Request IDInteiro4Identificador de comando: Um número usado para relacionar comandos às suas respectivas respostas. Ele é normalmente gerado pela entidade que enviou o comando e copiado no mesmo campo em um GetResponse pela entidade SNMP que está respondendo ao comando.
Error StatusInteiro (Enumeração)4Código de Erro: Um valor inteiro que é usado no GetResponse para indicar à entidade que emitiu o comando o resultado de sua requisição. Um código igual a zero indica que nenhum erro ocorreu; os outros valores indicam algum tipo de erro. A relação dos códigos de erro é apresentada na Tabela 3.
Error IndexInteiro4Índice do Erro: Quando o ErrorStatus for diferente de zero, este campo conterá um ponteiro para o objeto que gerou o erro. Caso haja mais de um objeto gerando erro, será apontado apenas o primeiro. Este campo é sempre zero em um comando.
Variable BindingsVariávelVariávelConjunto de Variáveis: Um conjunto de pares do tipo nome/valor que identificam os objetos da MIB dentro do PDU e seus respectivos valores.

Tabela 2: Formato do PDU exceto Trap.

Valor do Código de ErroCódigo de ErroDescrição
0noErrorNenhum erro ocorreu. Este código também é usado em todos os PDUs de comandos, visto que estes não possuem erros a relatar.
1tooBigO tamanho do PDU GetResponse seria muito grande para ser transmitido.
2noSuchNameO nome do objeto requisitado não foi encontrado.
3badValueAlgum valor no comando requisitado não está de acordo com a estrutura que o destinatário tem para o objeto. Por exemplo o tamanho ou o tipo do dado está incorreto.
4readOnlyFoi feita uma tentativa de alterar o valor de alguma variável cujo acesso é de apenas leitura.
5genErrOcorreu algum erro diferente dos especificados anteriormente.

Tabela 3: Relação de códigos de erro.

Conforme citado anteriormente, o PDU Trap possui um formato diferenciado. Esse formato é descrito na Tabela 4.

Nome do CampoTipoTamanho (bytes)Descrição
PDU TypeInteiro (Enumeração)4Tipo de PDU: Um valor inteiro que indica o tipo de PDU, que é 4 para o PDU Trap.
EnterpriseSequencia de InteirosVariávelEmpresa: Um identificador de objeto para um grupo, que indica o tipo de objeto que gerou o Trap.
Agent AddrEndereço de Rede4Endereço do Agente: O endereço IP do agente SNMP que gerou o Trap.
Generic TrapInteiro (Enumeração)4Código Genérico de Trap: Um valor que identifica o Trap entre um conjunto de códigos pré-definidos.
Specific TrapInteiro4Código Específico de Trap: Um valor que identifica um tipo de Trap especifico de uma implementação.
Time StampTimeTicks4Marcação de Tempo: A quantidade de tempo, desde a última inicialização, da entidade SNMP que enviou o Trap. Usado para registro de atividades.
Variable BindingsVariávelVariávelConjunto de Variáveis: Um conjunto de pares do tipo nome/valor que identificam os objetos da MIB dentro do PDU e seus respectivos valores.

Tabela 4: Formato do PDU Trap.

2.2. Mecanismos de segurança

Infelizmente, a segurança incorporada ao SNMPv1 é extremamente limitada e pode ser resumida em um conceito e uma tecnonogia.

  • Objetos Fracos: o SNMP foi criado com a idéia de que os objetos da MIB usados no protocolo seriam relativamente fracos. Isso significa que os objetos foram projetados para que qualquer problema que ocorresse na manipulação deles resultasse em um dano mínimo. Dessa forma a política do desenvolvimento do projeto era que os objetos da MIB que poderiam ser lidos não deveriam conter informações críticas, e os objetos que poderiam ser alterados não deveriam controlar nenhuma funcionalidade critica.
  • Strings de Comunidade: todos os dispositivos em uma rede SNMP administrados por um conjunto particular de gerentes são considerados como pertencentes a uma “comunidade”. Cada mensagem SNMPv1 trocada entre membros de uma comunidade são identificadas por uma string de comunidade que aparece em um campo do cabeçalho da mensagem. Essa string é como uma simples senha; qualquer mensagem recebida com a string de comunidade errada é rejeitada pelo destinatário.

Pode-se dizer que essas características de segurança são melhores do que nada, mas não muito. O uso de objetos fracos é comparável a uma regra que diz para não deixar o carro estacionado com as portas abertas e a chave na ignição – ela está dizendo basicamente para não procurar problemas. Isso é prudente, mas não é uma solução completa de segurança. O uso de strings de comunidade protege contra ataques óbvios na forma de mensagens não autorizadas, no entanto as strings são enviadas em texto puro e podem ser facilmente descobertas. Assim pode-se comparar a deixar seu carro estacionado com as portas trancadas: protege contra um ladrão casual, mas não contra um profissional.

É claro que para muita gente a segurança simplória fornecida pelo SNMPv1 é suficiente. No entanto, para novos e grandes ambientes de rede, principalmente os que englobam redes publicas de operadoras, o SNMPv1 não fornece nível suficiente de segurança.

3. O SNMP versão 2 (SNMPv2c)

Após alguns anos de uso do SNMPv1, certas deficiências passaram a ser percebidas e as necessidades de melhoria foram identificadas. Isso levou ao desenvolvimento da versão original do SNMPv2, que tinha como objetivo aprimorar o SNMPv1 em várias áreas, incluindo as definições de objetos da MIB, operações do protocolo e segurança. Esta última área, segurança, levou a proliferação de variantes do SNMPv2.

Visto que existem diferentes variações do SNMPv2, também existem variações nos formatos das mensagens utilizados para cada uma dessas variações. Isso é bastante confuso, mas seria muito pior caso as mensagens SNMP não possuíssem uma natureza modular. As operações do protocolo foram alteadas da versão SNMPv1 para o SNMPv2, e para isso foram necessárias alterações no formato do PDU. No entanto as operações do protocolo são as mesmas para todas as variações do SNMPv2. As diferenças entre as variações do SNMPv2 estão nas áreas de implementação de segurança. Dessa forma, o resultado é que o formato do PDU é o mesmo para todas as variantes do SNMPv2, mas o formato da mensagem difere de variação para variação.

Durante a divergência do SNMPv2, quatro variações foram definidas: o SNMPv2 original (chamado de SNMPv2p); o SNMPv2 baseado em comunidades (SNMPv2c); o SNMPv2 baseado em usuários (SNMPv2u) e o SNMPv2*. Todas as definições fazem referencia a RFC 1905 que define a estrutura do PDU do SNMPv2.

Neste artigo será abordado apenas o SNMPv2c, pois é a variação que tornou-se mais popular.

3.1. As Melhorias Introduzidas

Na versão 2 do SNMP foram introduzidas varias melhorias em relação à versão anterior, entre elas vale a pena destacar a possibilidade de comunicação entre entidades gerentes através das mensagens InformRequest, que tornou possível o gerenciamento distribuído.

Outras mudanças são a inserção de uma PDU para otimizar e facilitar a recuperação de dados em tabelas, o GetBulkRequest, novos objetos MIBs para comunicação gerente-gerente e alterações nos nomes e formatos de operações existentes.

3.2. As Mensagens

A variação SNMPv2c tinha como objetivo manter as melhorias introduzidas pelo SNMPv2p, mas voltar a utilizar o modelo simples de segurança do SNMPv1 com strings de comunidade. Dessa forma, o documento que define o SNMPv2c (RFC 1901) especifica que o formato geral da mensagem é o mesmo usado para o SNMPv1, com exceção do número de versão que foi alterado. Esse formato é descrito na Tabela 5.

Nome do CampoTipoTamanho (bytes)Descrição
VersionInteiro4Número da Versão: Indica a versão do SNMP da mensagem; usado para assegurar compatibilidade entre versões. Para o SNMPv2c, o valor usado é 1.
ComunityString de octetosVariávelNome da Comunidade: Identifica a comunidade SNMP em que o remetente da mensagem está localizado. Este campo é usado para implementar o mecanismo de segurança baseado em comunidades.
PDUVariávelProtocol Data Unit: O PDU que está sendo transmitido como corpo da mensagem.

Tabela 5: Formato da mensagem do SNMPv2c.

3.2.1. Os Tipos de PDU e seus Formatos

O formato dos PDUs no SNMPv2 á descrito na RFC 1905, e é similar ao do SNMPv1. Os PDUs do SNMPv2 possuem o mesmo formato, com exceção do PDU GetBulkRequest, que é uma novo tipo de PDU adicionado ao protocolo.

Nesta versão do SNMP foram incluídos dois novos tipos de PDU, o já citado GetBulkRequest e o InformRequest. Além destes, o PDU Trap foi alterado e não mais utiliza um formato específico de PDU. A descrição de cada PDU está na Tabela 6.

Valor do Tipo de PDUTipo de PDUDescrição
0GetRequestRetorna o valor de uma instância de variável.
1GetNextRequestRetorna o valor da variável sucessora lexicográfica.
2ResponseRetorna o resultado de uma operação.
3SetRequestAtribui valor a uma variável.
4Trap (obsoleto)Não usado. Era o antigo Trap do SNMPv1.
5GetBulkRequestPermite a recuperação de grande quantidade de dados, normalmente o conteúdo de tabelas.
6InformRequestPermite que um gerente envie informações para outro gerente.
7Trapv2Envia sinalizações de eventos.
8ReportUsado para comunicação interna do protocolo para relatar erros excepcionais ocorridos durante o processamento das requisições.

Tabela 6: Tipos e descrições dos PDUs

Nome do CampoTipoTamanho (bytes)Descrição
PDU TypeInteiro (Enumeração)4Tipo de PDU: um inteiro que identifica o tipo do PDU. Os valores e tipos possíveis estão na Tabela 6, exceto o 5 (GetBulkRequest) que possui PDU com formato diferenciado..
Request IDInteiro4Identificador de comando: Um número usado para relacionar comandos às suas respectivas respostas. Ele é normalmente gerado pela entidade que enviou o comando e copiado no mesmo campo em um GetResponse pela entidade SNMP que está respondendo ao comando.
Error StatusInteiro (Enumeração)4Código de Erro: Um valor inteiro que é usado no Response para indicar à entidade que emitiu o comando o resultado de sua requisição. Um código igual a zero indica que nenhum erro ocorreu; os outros valores indicam algum tipo de erro. A relação dos códigos de erro é apresentada na Tabela 9.Note que os primeiros seis valores estão mantidos da mesma forma como eram usados no SNMPv1 por motivos de compatibilidade. No entanto o SNMPv2 adiciona muitos outros códigos de erro que permitem uma indicação muito mais específica do tipo de erro ocorrido.
Error IndexInteiro4Índice do Erro: Quando o ErrorStatus for diferente de zero, este campo conterá um ponteiro para o objeto que gerou o erro. Caso haja mais de um objeto gerando erro, será apontado apenas o primeiro. Este campo é sempre zero em um comando.
Variable BindingsVariávelVariávelConjunto de Variáveis: Um conjunto de pares do tipo nome/valor que identificam os objetos da MIB dentro do PDU e seus respectivos valores.

Tabela 7: Formato do PDU, exceto GetBulkRequest.

O formato do PDU do GetBulkRequest é diferenciado e apresenta campos específicos para a funcionalidade de resgate de grandes quantidades de dados em tabelas. O formato desse PDU está descrito na Tabela 8.

Nome do CampoTipoTamanho (bytes)Descrição
PDU TypeInteiro (Enumeração)4Tipo de PDU: Um valor inteiro que indica o tipo de PDU, que é 5 para o PDU GetBulkRequest.
Request IDInteiro4Identificador de comando: Um número usado para relacionar comandos às suas respectivas respostas. Ele é normalmente gerado pela entidade que enviou o comando e copiado no mesmo campo em um GetResponse pela entidade SNMP que está respondendo ao comando.
Non RepeatersInteiro4Não Repetidos: Especifica o número de objetos que não serão lidos repetidamente, a partir do início da lista de objetos do comando.
Max RepetitionsInteiro4Número Máximo de Repetições: O número máximo de iterações que deverão ser executadas para os objetos que seguem os não repetidos do comando.
Variable BindingsVariávelVariávelConjunto de Variáveis: Um conjunto de pares do tipo nome/valor que identificam os objetos da MIB dentro do PDU e seus respectivos valores.

Tabela 8: Formato do PDU do GetBulkRequest.

Os códigos de erro também tiveram alteração na versão 2 do SNMP, foram adicionados vários códigos novos para permitir um maior detalhamento quando ocorresse algum problema no processamento do comando. A Tabela 9 lista os códigos de erro possíveis.

Valor do Código de ErroCódigo de ErroDescrição
0noErrorNenhum erro ocorreu. Este código também é usado em todos os PDUs de comandos, visto que estes não possuem erros a relatar.
1tooBigO tamanho do PDU Response seria muito grande para ser transmitido.
2noSuchNameO nome do objeto requisitado não foi encontrado.
3badValueAlgum valor no comando requisitado não está de acordo com a estrutura que o destinatário tem para o objeto. Por exemplo o tamanho ou o tipo do dado está incorreto.
4readOnlyFoi feita uma tentativa de alterar o valor de alguma variável cujo acesso é de apenas leitura.
5genErrOcorreu algum erro diferente dos especificados nesta tabela.
6noAccessO acesso ao objeto foi negado por questões de segurança.
7wrongTypeO tipo de dados do objeto no conjunto de variáveis está incorreto para o objeto.
8wrongLengthO tamanho do objeto especificado no conjunto de variáveis está incorreto para o objeto.
9wrongEncodingO valor codificado é inconsistente com o tipo do objeto.
10wrongValueO valor de uma dada variável não é válido para o objeto.
11noCreationUma variável especificada não existe e não pode ser criada.
12inconsistentValueO valor especificado não pode ser atribuído à variável neste momento, é uma condição temporária.
13resourceUnavailableUma tentativa de atribuir um valor a uma variável requereu alocação de recursos que estão indisponíveis no momento.
14commitFailedNão foi possível realizar todas as atribuições de variável.
15undoFailedNão foi possível desfazer as atribuições de variáveis após a ocorrência de uma falha.
16authorizationErrorErro de autorização.
17notWritableA variável não pode ser modificada.
18inconsistentNameO nome da variável especificada não existe e não pode ser criada nas circunstâncias atuais.

Tabela 9: Códigos de erro do SNMPv2.

Os códigos de erro noSuchName (2), badValue (3) e readOnly (4) foram mantidos apenas para compatibilidade e não são gerados pelo SNMPv2.

3.3. Mecanismos de segurança

Visto que a definição do SNMPv2c tem como objetivo manter as melhorias de funcionalidade do SNMPv2p, porém sem utilizar o mecanismo de segurança especificado para o mesmo, os mecanismos de segurança disponíveis para o SNMPv2c são exatamente os mesmos do SNMPv1.

4. O SNMP versão 3 (SNMPv3)

O SNMP versão 3 foi criado para suprir uma necessidade padronização que se fez necessária com as várias variações do SNMPv2 quem tentavam criar soluções de segurança para o protocolo. O SNMPv3 teve como base as definições das variações SNMPv2u e SNMPv2*.

Além das definições das questões de segurança, o projeto do SNMPv3 também objetivou uma padronização de implementação das entidades (agente/gerente), modularizando suas funcionalidades, o que facilita a evolução de alguns mecanismos do protocolo sem exigir que novas versões sejam lançadas. Outros objetivos eram a manutenção de uma estrutura simples, facilitar a integração com outras versões e, sempre que possível, reaproveitar as especificações existentes.

O SNMPv3 incorporou o SMI e o MIB do SNMPv2, assim como também utilizou as mesmas operações do SNMPv2, apenas com uma reescrita da norma para uma compatibilização da nomenclatura.

4.1. A organização interna (arquitetura)

A arquitetura proposta na RFC 2271 consiste em uma coleção distribuída de entidades SNMP que interagem entre si. Cada entidade implementa uma porção das capacidades do SNMP e pode atuar como agente, gerente ou uma combinação dos dois. Cada entidade SNMP consiste em uma colação de módulos que interagem entre si para prover serviços.

4.1.1. Entidades

Cada entidade incluí apenas um engine SNMP. Um engine SNMP implementa funções para enviar e receber mensagens, autenticar e encriptar/decriptar mensagens, e controlar o acesso aos objetos gerenciados. Essas funções são providas na forma de serviços para uma ou mais aplicações que são configuradas em conjunto com o engine para formar uma entidade SNMP.

Tanto o engine SNMP quanto as aplicações que ele suporta são definidos como uma coleção de módulos. Essa arquitetura prove várias vantagens. Primeiro, o papel de uma entidade SNMP é determinado por quais módulos estão implementados nessa entidade. Por exemplo existem conjuntos de módulos que são necessários para um agente SNMP, enquanto outros são requeridos para um gerente SNMP. Segundo, a estrutura modular da especificação permite a definição de diferentes versões para cada módulo. Por sua vez, isso torna possível:

  • Definir capacidades alternativas ou melhoradas para certos aspectos do SNMP sem precisar levar todo o padrão para uma nova versão;
  • Especificar de forma clara estratégias de coexistência e transição.

A Figura 1 exibe de forma ilustrativa os componentes e as interações dos módulos de uma entidade SNMP.

Figura 1: Layout de uma entidade SNMP.

Todo engine SNMP é identificado com um número chamado de snmpEngineID.

4.1.1.1. Gerentes

Um gerente SNMP tradicional interage com os agentes SNMP enviando comandos (get, set) e recebendo mensagens trap; o gerente também pode interagir com outros gerentes enviando PDUs do tipo InformRequest, que fornece alertas, e recebendo InformResponse PDUs, que confirma o recebimento de InformRequest. Na terminologia do SNMPv3, um gerente tradicionalmente inclui três categorias de aplicações. As Aplicações Geradoras de Comandos monitoram e manipulam dados gerenciados nos agentes remotos; eles utilizam os PDUs do SNMPv1 e/ou do SNMPv2, incluindo Get, GetNext, GetBulk e Set. As Aplicações Emissoras de Notificações iniciam mensagens assíncronas; no caso de um gerente tradicional, o PDU InformRequest é usado por essas aplicações. Uma Aplicação Recebedora de Notificações processa as mensagens assíncronas que chegam; isso inclui os PDUs InformRequest, Trapv2 e Trap. No caso do PDU que chegar for um InformRequest, a Aplicação Recebedora de Notificações responderá com o PDU Response.

Todas as aplicações descritas usam os serviços providos pelo engine SNMP da entidade. O engine SNMP executa dois papeis básicos:

  • Ele aceita PDUs de saída das aplicações SNMP, executa os processamentos necessários, inclusive inserir códigos de autenticação e encriptação, e então encapsula os PDUs em mensagens para transmissão;
  • Ele aceita mensagens SNMP provenientes da camada de transporte, executa os processamentos necessários, inclusive autenticação e decriptação, então extrai os PDUs das mensagens e passa-os para a aplicação SNMP apropriada.

Em um gerente tradicional, o engine SNMP contém um Despachante (Dispatcher), um Subsistema de Processamento de Mensagens (Message Processing Subsystem) e um Subsistema de Segurança (Security Subsystem).

O Despachante é um simples gerenciador de tráfego. Para PDUs de saída, o Despachante aceita os PDUs vindos das aplicações e executa as seguintes funções: para cada PDU, o Despachante determina o tipo de processamento de mensagem requerido (SNMPv1, SNMPv2c ou SNMPv3) e passa o PDU para o módulo de processamento de mensagem apropriado no Subsistema de Processamento de Mensagens. Subseqüentemente, o Subsistema de Processamento de Mensagens retorna uma mensagem contendo o PDU e os cabeçalhos apropriados. O Despachante então mapeia a mensagem na camada de transporte para transmissão. No caso de mensagens de entrada, o Despachante aceita a mensagem vinda da camada de transporte e executa as seguintes funções: o Despachante encaminha cada mensagem para o módulo de processamento adequado. Subseqüentemente, o Subsistema de Processamento de Mensagens retorna o PDU contido na mensagem. O Despachante então passa o PDU para a aplicação apropriada.

O Subsistema de Processamento de Mensagens aceita PDUs de saída vindos do Despachante e prepara-os para transmissão encapsulando-os com o cabeçalho apropriado e retornando-os para o Despachante. O Subsistema de Processamento de Mensagens também aceita mensagens de entrada vindas do Despachante, processa cada cabeçalho da mensagem, e retorna o PDU para o Despachante. Uma implementação do Subsistema de Processamento de Mensagens pode suportar apenas um formato de mensagem correspondente a uma das versões do SNMP, ou ele pode conter um certo número de módulos, cada um suportando uma versão diferente do SNMP.

O Subsistema de Segurança executa funções de autenticação e criptografia. Cada mensagem de saída é passada para o Subsistema de Segurança pelo Subsistema de Processamento de Mensagens. Dependendo dos serviços requeridos, o Subsistema de Segurança pode criptografar o PDU e possivelmente alguns outros campos do cabeçalho da mensagem, e ele pode também gerar um código de autenticação e inseri-lo no cabeçalho da mensagem. A mensagem processada é então devolvida para o Subsistema de Processamento de Mensagens. De maneira similar, cada mensagem de entrada é passada para o Subsistema de Segurança pelo Subsistema de Processamento de Mensagens. Se requerido, o Subsistema de Segurança verifica o código de autenticação e executa a descriptografia. Então a mensagem processada é passada de volta para o Subsistema de Processamento de Mensagens. Uma implementação do Subsistema de Segurança pode suportar um ou mais modelos de segurança distintos. Até o momento, o único modelo de segurança definido é o Modelo de Segurança Baseado em Usuário (USM) para o SNMPv3, especificado na RFC 2274.

Uma representação visual da entidade gerente pode ser observada na Figura 2.

Figura 2: Entidade Gerente do SNMPv3.

4.1.1.2. Agentes

Um agente SNMP tradicional pode conter três tipos de aplicação: a Aplicação que Responde Comandos prove acesso aos dados gerenciados. Estas aplicações respondem às requisições que chegam recuperando ou alterando objetos gerenciados e então gerando um PDU Response. Uma Aplicação Emissora de Notificações inicia mensagens assíncronas; no caso de um agente tradicional, o PDU Trapv2 ou Trap são usados por essa aplicação. Uma Aplicação Encaminhadora Proxy encaminha mensagens entre entidades.

O engine SNMP de um agente tradicional contém todos os componentes encontrados em um engine SNMP de um gerente tradicional, mais um Subsistema de Controle de Acesso. Esse subsistema provém serviços de autorização para controlar o acesso às MIBs quanto à leitura e gravação em objetos gerenciados. Esses serviços são executados com base no conteúdo dos PDUs. Uma implementação do Subsistema de Segurança pode suportar um ou mais modelos de controle de acesso distintos. Até o momento o único modelo de segurança definido é o Modelo de Acesso Baseado e Visões (VACM) para o SNMPv3, especificado na RFC 2275.

Uma representação visual da entidade agente pode ser observada na Figura 3.

Figura 3: Entidade Agente SNMPv3.

4.2. As Mensagens

Entre as mudanças significativas trazidas pelo SNMPv3 está uma maneira mais flexível de definir métodos e parâmetros de segurança, para permitir a coexistência de múltiplas técnicas de segurança.

O formato geral das mensagens no SNMPv3 ainda segue a mesma idéia de uma mensagem “envelope” que contém um cabeçalho e um PDU encapsulado. No entanto, na versão 3 esse conceito está ainda mais refinado. Os campos do cabeçalho foram divididos em dois tipos: os que lidam e os que não lidam com questões de segurança. Os campos não voltados para segurança são comuns para todas as implementações do SNMPv3, enquanto o uso dos campos ligados a segurança podem ser guiados por cada modelo de segurança do SNMPv3, e processados pelos módulos correspondentes em uma entidade SNMP que lide com segurança. Esta solução provê uma considerável flexibilidade evitando os problemas que atormentaram o SNMPv2.

Uma descrição mais detalhada do novo formato de mensagem introduzida no SNMPv3 pode ser encontrada nas Tabelas 10, 11 e 12.

Nome do CampoTipoTamanho (bytes)Descrição
Msg VersionInteiro4Número de Versão da Mensagem: Indica a versão do SNMP da mensagem; usado para assegurar compatibilidade entre versões. Para o SNMPv3, esse valor é 3.
Msg IDInteiro4Identificador da Mensagem: Um número usado para identificar uma mensagem SNMPv3 e encontrar as mensagens de resposta de um commando enviado. O uso deste campo é similar ao RequestID descrito no formato do PDU, mas eles não são idênticos. Este campo foi criado para permitir a identificação no nivel de processamento da mensagem sem lever em consideração o conteúdo do PDU, para proteger contra certos ataques à segurança. Dessa forma o Msg ID e o Request ID são usados de forma independente.
Msg Max SizeInteiro4Tamanho Máximo da Mensagem: O tamanho máximo da mensagem que o remetente dessa mensagem pode receber. O valor mínimo desse campo é 484.
Msg FlagsOcteto1Sinalizadores de Mensagem: Um conjunto de sinalizadores que controlam o processamento da mensagem. A estrutura atual desse campo está descrita na Tabela 11.
Msg Security ModelInteiro4Modelo de Segurança da Mensagem: Um valor inteiro que indica qual modelo de segurança foi usado para essa mensagem. Para o modelo de segurança baseado em usuários (o padrão do SNMPv3) este valor é 3.
Msg Security ParametersVariávelParametros de Segurança da Mensagem: Um conjunto de campos que contêm parâmetros requeridos para implementar o modelo de segurança em particular usado na mensagem. Os conteúdos desse campo são especificados em cada documento que descreva um modelo de segurança do SNMPv3. Por exemplo, os parâmetros para o modelo baseado em usuários estão na RFC 3414.
Scoped PDUVariávelPDU Com Escopo: Contém o PDU que será transmitido, juntamente com parâmetros que identificam um contexto SNMP. Esse contexto descreve um conjunto de informações gerenciais acessíveis à uma entidade em particular. O PDU é chamado “Com Escopo” porque está aplicado dentro do escopo de um contexto. Este campo pode ou não estar criptografado dependendo do valor do sinalizador Priv Flag. A estrutura deste campo está descrita na Tabela 12.

Tabela 10: Formato da mensagem do SNMPv3.

Nome do SubcampoTamanho (bytes)Descrição
Reserved5/8
(5 bits)
Reservado: Reservado para uso futuro.
Reportable Flag1/8
(1 bit)
Sinalizador de Resposta: Quando igual a 1, um dispositivo recebendo esta mensagem deve enviar de volta um PDU Report quando determinada condição for alcançada que demande a geração do PDU.
Priv Flag1/8
(1 bit)
Sinalizador de Privacidade: Quando igual a 1, indica que foi usada criptografia para proteger a privacidade da mensagem. Somente pode ser igual a 1 quando o Auth Flag também for igual a 1.
Auth Flag1/8
(1 bit)
Sinalizador de Autenticação: Quando igual a 1, indica que autenticação foi usada para proteger a autenticidade da mensagem.

Tabela 11: Descrição dos sinalizadores de mensagem (Message Flags).

Nome do SubcampoTipoTamanho(bytes)Descrição
Context Engine IDString de OctetosVariávelContext Engine ID: Usado para identificar para qual aplicação o PDU será entregue para processamento.
Context NameString de OctetosVariávelNome do Contexto: Um identificados de objeto que especifica o contexto associado ao PDU.
PDUVariávelPDU: A unidade de dados do protocolo sendo transmitida.

Tabela 12: Descrição do campo PDU Com Escopo (Escoped PDU).

4.2.1. Os tipos de PDU e seus formatos

Como o SNMPv3 utiliza as mesmas operações do SNMPv2, a RFC 3416 que define os formatos de PDU do SNMPv3 é apenas uma atualização da RFC 1904. Sendo assim os PDUs do SNMPv3 são iguais aos do SNMPv2 listados anteriormente.

4.3. Mecanismos de segurança

Antes de começar a descrever os mecanismos de segurança definidos no SNMPv3, é interessante relacionar os novos termos que foram inseridos nessa versão e que estão associados a várias questões de segurança.

  • snmpEngineID: um identificador único e livre de ambigüidade atribuído a um engine SNMP. Serve também para identificar a entidade SNMP que contem o engine, visto que a relação de um-para-um entre engines e entidades.
  • contextEngineID: identifica unicamente uma entidade SNMP que pode conter uma instância de um context com um contextName particular.
  • contextName: identifica um contexto particular dentro de um engine SNMP. Ele á passado como parâmetro para o Despachante e o Subsistema de controle de acesso.
  • principal: a entidade em nome da qual os serviços são providos ou o processamento ocorre. Um principal pode ser um indivíduo atuando com um papel particular; um conjunto de indivíduos, com cada um atuando com um papel particular; uma aplicação ou conjunto de aplicações; uma combinação destes.
  • securityName: uma string legível que representa um principal. Ela é passada como parâmetro em todas as primitivas SNMP (Despachante, Processamento de Mensagens, Segurança e Controle de Acesso).

4.3.1. O modelo de segurança baseado em usuários

A RFC 2274 define o modelo de segurança baseado em usuários (USM). O USM provê serviços de autenticação e privacidade ao SNMP. Especificamente, o USM foi projetado para fornecer segurança contra as seguintes principais ameaças:

  • Modificação de Informação: uma entidade poderia alterar uma mensagem em transito gerada por uma entidade autorizada de forma a conseguir acesso não autorizado às operações gerenciais, inclusive alterar valores dos objetos. A essência desse ameaça é que uma entidade não autorizada poderia alterar qualquer parâmetro gerencial, inclusive os relacionados a configuração, operação e contabilização.
  • Mascaramento: operações gerenciais que não são permitidas para uma dada entidade podem ser executadas por essa entidade caso ela assuma a identidade de uma entidade autorizada.
  • Modificação da Cadeia de Mensagem: o SNMP foi projetado para operar sobre um protocolo de transporte não orientado a conexão. Existe uma ameaça em que mensagens SNMP poderiam ser reordenadas, atrasadas ou repetidas (duplicadas) para efetuar operações gerenciais não autorizadas. Por exemplo, uma mensagem para reiniciar um dispositivo poderia ser copiada e repetida posteriormente.
  • Descoberta: uma entidade poderia observar trocas de mensagens entre gerente e agente e dessa forma, descobrir valores de objetos gerenciais e notificações de eventos. Por exemplo, a observação de um comando Set que altere alguma senha habilitaria um atacante a descobrir a nova senha.

O USM não tem como objetivo oferecer segurança para as seguintes ameaças:

  • Negação de Serviço (Denial of Serviçe – DoS): um atacante pode evitar a troca de mensagens entre um gerente e um agente.
  • Analise de Tráfego: um atacante poderia observar a forma genérica como se comporta o trafego entre um gerente e um agente.

A falta de um contador para evitar as ameaças do tipo DoS pode ser justificada de duas formas: primeiro, os ataques do tipo DoS, em muitos casos, não podem ser distinguidos do tipo de falha de rede para a qual uma aplicação de gerência de rede deve saber lidar; e segundo, um ataque do tipo DoS tem como objetivo impedir toda troca de informações, portanto é uma questão pra ser tratada por uma solução de segurança mais abrangente, não apenas para uma que esteja embutida dentro de um protocolo de gerenciamento. Quanto à análise de trafego, muitas das características do tráfego de gerenciamento de rede são previsíveis (por exemplo, entidades podem ser gerenciadas via comandos SNMP que são enviados de forma regular por uma ou mais estações de gerenciamento) e dessa forma não há nenhuma vantagem significativa em proteger contra esse tipo de observação.

4.3.2. O modelo de segurança baseado em visões

Controle de acesso é uma função de segurança executada em nível de PDU. Um documento de controle de acesso define mecanismos para determinar se um acesso a um objeto gerenciado na MIB local pode ser permitido para um determinado sistema remoto. É concebível que vários mecanismos de controle de acesso podem ser definidos. A documentação do SNMPv3 define o Modelo de Segurança Baseado em Visões (VACM).

O VACM tem duas principais características:

  • O VACM determina se o acesso a um objeto gerenciado na MIB local deve ser acessado por um sistema remoto;
  • O VACM faz uso de uma MIB que:
    • Define a política de controle de acesso para o agente
    • Torna possível a utilização de configuração remota.

A RFC 2275 define cinco elementos que compõe o VACM: grupos, níveis de segurança, contextos, visões MIB e políticas de acesso.

4.3.2.1. Grupos

Um grupo é definido como um conjunto de zero ou mais duplas do tipo , com base nas quais os objetos gerenciados do SNMP podem ser acessados. Um securityName se refere a um principal, e os direitos de acesso para todos os principais em um dado grupo são idênticos. Um groupName único é associado a cada grupo. O conceito de grupo é uma ferramenta útil para categorizar gerentes com respeito a seus direitos de acesso. Por exemplo todos os gerentes de alto nível têm um determinado conjunto de direitos de acesso, enquanto os gerentes de nível intermediário têm um conjunto de direitos de acesso completamente diferente.

Uma determinada combinação de securityModel e securityName pode pertencer a no máximo um grupo. Ou seja, para um agente, um determinado principal cuja comunicação está protegida por um determinado securityModel pode apenas estar incluído em um grupo.

4.3.2.2. Níveis de Segurança

Os direitos de acesso para um grupo podem variar de acordo com o nível de segurança da mensagem que contém a requisição. Por exemplo, um agente pode permitir um acesso de somente leitura para uma requisição comunicada em uma mensagem não autenticada, mas pode requerer autenticação para permitir acesso de escrita. Dessa forma, para certos objetos críticos, o agente pode requerer que a requisição e sua resposta sejam transmitidas usando serviço de segurança.

4.3.2.3. Contextos

Um contexto é um subconjunto nomeado das instâncias de objetos na MIB local Os contextos provêm uma maneira de agregar objetos em coleções com diferentes políticas de acesso.

O contexto é um conceito que está relacionado com o controle de acesso. Quando uma estação gerente interage com um agente para acessar informações gerenciadas, essa interação ocorre entre um principal do gerente e o engine SNMP do agente, e os privilégios de controle de acesso são expressados em uma visão MIB que se aplica a esse principal e a esse contexto. Contextos têm as seguintes características:

  • Uma entidade SNMP, identificada unicamente por um contextEngineID, pode manter mais de um contexto;
  • Um objeto ou uma instância de objeto pode aparecer em mais de um contexto;
  • Quando múltiplos contextos existirem, para identificar uma instância individual de um objeto, o seu contextName e contextEngineID precisam ser identificados além do seu tipo de objeto e sua instância.

4.3.2.4. Visões MIB

São freqüente as situações em que desejamos restringir o acesso de um grupo em particular a um subconjunto dos objetos gerenciados de um agente. Para alcançar esse objetivo, o acesso a um contexto é executado através de uma visão MIB, que define um conjunto específico de objetos gerenciados (e opcionalmente instâncias específicas de objetos). O VACM faz uso de uma técnica poderosa e flexível para definir visões MIB, baseada no conceito de visão de subárvore e visão de famílias. A visão MIB é definida nos termos de uma coleção, ou família, ou subárvores, com cada subárvore sendo incluída ou excluída da visão.

Os objetos gerenciados de uma base local são organizados de forma hierárquica (em forma de árvore), baseado nos identificadores de cada objeto. Essa base local compreende um subconjunto de todos os tipos de objetos definidos de acordo com o SMI (Structure of Management Information), e inclui instâncias de objetos cujos identificadores estão em conformidade com as convenções do SMI.

O SNMPv3 introduz o conceito de subárvore. Uma subárore é apenas um nó, e seus elementos subordinados, na hierarquia de nomes da MIB. De forma mais formal, uma subárvore pode ser definida como o conjunto de todos os objetos e instâncias de objetos que possuem um mesmo Identificador de Objeto ASN.1 como prefixo de seus nomes. O mais longo prefixo em comum de todas as instancias de uma subárvore é o identificador de objeto do nó pai dessa subárvore.

A cada entrada na vacmAccessTable estão associadas três visões MIB, cada uma para um tipo de acesso (leitura, escrita e notificação). Cada visão MIB consiste em um conjunto de visões de subárvores. Cada visão de subárvore na visão MIB é especificada como sendo incluída ou excluída. Ou seja, a visão MIB inclui ou exclui todas as instâncias de objetos contidas em uma subárvore. Além disso, uma máscara de visão é definida para reduzir a quantidade de informações de configuração necessárias quando uma maior granularidade é requerida (por exemplo, controle de acesso ao nível de uma instância de objeto).

4.3.2.5. Políticas de Acesso

O VACM permite ao engine SNMP ser configurado de forma a aplicar um conjunto específico de direitos de acesso. A determinação do acesso depende dos seguinte fatores:

  • principal que está fazendo a requisição de acesso. O VACM torna possível que um agente permita diferentes privilégios de acesso para usuários diferentes. Por exemplo, um sistema gerente responsável pela configuração de toda uma rede pode ter uma vasta autoridade para alterar itens nas MIBs locais, enquanto um gerente de nível intermediário com responsabilidade de monitoramento pode direito de leitura apenas, e pode ainda ser limitado a acessar apenas um subconjunto das MIBs locais. Como visto anteriormente, principais são atribuídos a grupos a as políticas de acesso são especificadas com relação a grupos.
  • nível de acesso pelo qual a requisição foi comunicada em uma mensagem SNMP. Normalmente um agente vai requerer o uso de autenticação para mensagens contendo uma requisição do tipo set (operação de escrita).
  • modelo de segurança usado para processar a mensagem de requisição. Se um agente implementa múltiplos modelos de segurança, o agente pode ser configurado para prover diferentes níveis de acesso para as requisições que foram comunicadas por mensagens processadas por diferentes modelos de segurança. Por exemplo, certos itens podem estar acessíveis caso a requisição veio em uma mensagem que deve ser processada pelo USM, mas podem não estar acessíveis se forem processadas pelo modelo do SNMPv1.
  • contexto MIB da requisição.
  • instância de objeto específica para a qual o acesso está sendo requerido. Alguns objetos carregam informações mais críticas ou sensíveis do que outros, e dessa forma a política de acesso deve depender especificamente da instância de objeto que está sendo requisitada.
  • tipo de acesso requisitado (leitura, escrita ou notificação). A leitura, a escrita e a notificação são operações gerenciais distintas e políticas de controle de acesso diferentes precisam ser aplicadas para cada uma dessas operações.

5. Conclusão

Com base nas informações apresentadas pode-se verificar que o SNMPv3 possui várias características que o torna muito mais seguro que suas versões anteriores, no entanto esse benefício de segurança vem acompanhado de uma maior complexidade para configurar todas as funcionalidades de segurança necessárias.

Dessa forma, para ambientes em que haja necessidade de uma implementação rápida e que segurança não seja uma questão crítica, é justificado o uso do SNMPv1, ou preferencialmente, do SNMPv2c.

No entanto, para ambientes em que a segurança é uma questão crucial, se faz necessário a utilização do SNMPv3, para que nem os dispositivos gerenciados nem as informações gerenciais sejam comprometidas.

6. Referências

STALLINGS, WILLIAN – SNMPv3: A Security Enhancement for SNMP, http://www.comsoc.org/livepubs/surveys/public/4q98issue/stallings.html – Acessado em 25/04/2008.

STALLINGS, WILLIAN – SNMP, SNMPv2, SNMPv3, RMON AND RMON2 Pratical Network Management. 3.ed. USA:Addison- Wesley, 1999.

TCP/IP Guide – http://www.tcpipguide.com/free/t_TCPIPSimpleNetworkManagementProtocolSNMPProtocol.htm – Acessado em 25/04/2008.

Duplicando um Database Oracle à partir de um backup

Essa atividade é normalmente referida como Duplicação da base (duplicate database) ou Clone da base (clone database) e consiste basicamente em criar uma copia do database em uma outra instância, sem afetar o database original.

A duplicação pode ser feita de duas formas

  • A partir do database original ativo, chamado de from active database; ou
  • A partir de um backup do database original.

Existem várias situações que podem exigir que você crie uma cópia de um Database, entre as mais comuns está a duplicação de uma base de produção para validar a aplicação de um patch importante e de alto risco no ambiente. Outra situação que pode solicitar essa atividade é restaurar uma versão antiga do banco para recuperação de dados que podem ter sido deletados ou expurgados, sendo que essa recuperação tem que ser feita em paralelo à base atual.

Nota: Com o lançamento da versão 12c e da feature Multitenant, o processo de duplicação de CDB (container databases) e PDB (pluggable databases) difere um pouco do que é exposto aqui. Este procedimento de aplica a databases non-CDB (que é basicamente o conceito de database único por instância ao qual estávamos acostumados até a versão 11g).

Neste artigo irei duplicar um database chamado “erp” para um database chamado “clone”. O tipo de duplicação demonstrada aqui será a partir de um backup do database “erp”.

Criando um novo database para receber a cópia da base

Essa é a primeira etapa para o processo de duplicação. Por praticidade eu normalmente crio esse database usando o assistente “dbca”. Isso facilita bastante o processo.

Configurando o novo database para o processo de duplicação

Essa atividade vai depender do tipo de database que foi criado para receber a cópia. Caso o seu ambiente seja em cluster (RAC) você pode ter escolhido criar um database em RAC, RAC One Node, ou Single Instance.
No meu caso, o ambiente é um RAC e eu costumo criar o database como RAC One Node. Mas a configuração não difere muito de uma base em RAC tradicional. No caso de uma Single Instance seria até mais simples e você pode ignorar algumas configurações que não se aplicam.

A primeira configuração é restringir que o database inicie sua instância em apenas um nó do cluster, para isso altere os “candidate server” para apenas um dos hosts do cluster e altere o parâmetro “cluster_database” para false;

Verificando em qual nó do cluster a instancia RAC One Node está executando.

[oracle@ol7db01 ~]$ srvctl status database -d clone
Instance clone_1 is running on node ol7db01
Online relocation: INACTIVE

Tenha atenção para o nome da instância impressa no comando acima, você deverá usá-la mais adiante no configuração do listener.ora.

Verificando as configurações do database, mais especificamente quais os candidate servers onde ela pode iniciar.

[oracle@ol7db01 ~]$ srvctl config database -d clone
Database unique name: clone
Database name: clone
Oracle home: /u01/app/oracle/product/12.1.0/dbhome_1
Oracle user: oracle
Spfile: +DATA/CLONE/PARAMETERFILE/spfile.321.903414607
Password file: +DATA/CLONE/PASSWORD/pwdclone.279.903412795
Domain:
Start options: open
Stop options: immediate
Database role: PRIMARY
Management policy: AUTOMATIC
Server pools:
Disk Groups: DATA,RECO
Mount point paths:
Services: srvcloneon
Type: RACOneNode
Online relocation timeout: 30
Instance name prefix: clone
Candidate servers: ol7db01,ol7db02
OSDBA group: dba
OSOPER group: oper
Database instances:
Database is administrator managed

Alterando a relação de candidate servers para conter apenas o nó atual onde está executando.

[oracle@ol7db01 ~]$ srvctl modify database -d clone -e ol7db01

O passo seguinte é alterar o arquivo de configuração do Listener no host do cluster onde a instância desse database vai ser iniciada. Normalmente não há entradas fixas para as instâncias nas configurações do listener, ficando a cargo dos databases se registrarem automaticamente no listener após sua inicialização. No entanto, como durante processo de duplicação o RMAN executa shutdown e start na instância, para que o start funcione é necessário que haja uma entrada fixa no listener.

Primeiro verifique o caminho do arquivo de configuração do Listener.

[grid@ol7db01 ~]$ lsnrctl status
LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 10-FEB-2016 18:37:54
Copyright (c) 1991, 2014, Oracle.  All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 12.1.0.2.0 - Production
Start Date                08-FEB-2016 18:07:03
Uptime                    2 days 0 hr. 30 min. 51 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/12.1.0/grid/network/admin/listener.ora
Listener Log File         /u01/app/grid/diag/tnslsnr/ol7db01/listener/alert/log.xml
Listening Endpoints Summary...

Em seguida edite o arquivo adicionando ao seu final uma entrada conforme abaixo. Atenção para colocar o ORACLE_HOME e o SID_NAME corretos do seu ambiente.

SID_LIST_LISTENER =
 (SID_LIST =
  (SID_DESC =
    (GLOBAL_DBNAME = clone)
    (ORACLE_HOME = /u01/app/oracle/product/12.1.0/dbhome_1)
    (SID_NAME = clone_1)
   )
 )

Execute um reload no listener para ativar a alteração efetuada no arquivo listener.ora.

[grid@ol7db01 ~]$ lsnrctl reload
LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 10-FEB-2016 18:59:33
Copyright (c) 1991, 2014, Oracle.  All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER)))
The command completed successfully

A próxima etapa é configurar para que seja possível conectar na instância enquanto ela estiver iniciada em NOMOUNT. Deve-se adicionar o parâmetro UR = A no tnsnames.ora do servidor onde será executado o RMAN.
Além desse parâmetro, caso você esteja em um ambiente em RAC como o meu, provavelmente a entrada no tnsnames está com o host apontando para o endereço SCAN do cluster, Você deve alterar para endereço VIP do host onde a instância está configurada para iniciar.

CLONEDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ol7db01-vip)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = clone)
      (UR = A)
    )
  )

A seguir altere o parâmetro cluster_database para false.

[oracle@ol7db01 ~]$ sqlplus sys@clone as sysdba
SQL*Plus: Release 12.1.0.2.0 Production on Wed Feb 10 18:44:53 2016
Copyright (c) 1982, 2014, Oracle.  All rights reserved.
Enter password:
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Advanced Analytics and Real Application Testing options
SQL> show parameter cluster;
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
cluster_database                     boolean     TRUE
cluster_database_instances           integer     2
cluster_interconnects                string
SQL> alter system set cluster_database=false scope=spfile;
System altered.
SQL>

O próximo passo é parar o database clone e iniciá-lo no mono NOMOUNT.

[oracle@ol7db01 ~]$ srvctl stop database -d clone
[oracle@ol7db01 ~]$ srvctl start database -d clone -o nomount

Nesse ponto o database de destino (clone) está pronto para o processo de duplicação da base de origem (erp).

Preparando o backup do database de origem

Precisamos agora ter um backup full do database original para fazer a duplicação a partir do mesmo. Caso você esteja executando este procedimento para resgatar uma versão antiga de alguma tabela, já deve ter esse backup disponível.
Para este laboratório vou criar um backup full agora.

[oracle@ol7db01 ~]$ rman target sys@erp catalog rman@rcat
Recovery Manager: Release 12.1.0.2.0 - Production on Wed Feb 10 19:22:42 2016
Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.
target database Password:
connected to target database: ERP (DBID=152032381)
recovery catalog database Password:
connected to recovery catalog database
RMAN> run {
crosscheck archivelog all;
backup as compressed backupset database;
backup current controlfile;
backup spfile;
sql 'alter system archive log current';
backup as compressed backupset archivelog all delete input;
}2> 3> 4> 5> 6> 7> 8>

Depois de ter o backup disponível, certifique-se de que ele esteja acessível pelo servidor/instância onde está a base de destino (clone). Como neste laboratório o database de destino está no mesmo RAC do database de origem, e o backup está no diskgroup +RECO compartilhado no ASM, o acesso aos arquivos de backup não é um problema.

Mas se esse não é o seu caso, basta colocar os arquivos de backup em um diretório no servidor do database de destino e catalogar os arquivos com o comando do RMAN “catalog start with”.

Nota: Se você está usando algum backup antigo para a duplicação do database deve ter atenção na hora de especificar a clausula UNTIL no script de duplicação. Eu normalmente uso UNTIL SCN para esses casos de restore mais antigo por ser mais específico. Para identificar o SCN correto basta usar o maior Next SCN presente no backupset, caso o backup tenha sido feito em um database Single Instance. No caso de um database com mais de uma instância, obtenha o maior Next SCN de cada thread e entre esses escolha o menor deles.

RMAN> list backupset completed between "to_date('2016-02-10 00:00:00','YYYY-MM-DD HH24:MI:SS')" and "to_date('2016-02-10 23:00:00','YYYY-MM-DD HH24:MI:SS')";

List of Backup Sets
===================

BS Key  Type LV Size       Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
74      Full    106.63M    DISK        00:00:49     10-FEB-16
        BP Key: 76   Status: AVAILABLE  Compressed: YES  Tag: TAG20160210T192350
        Piece Name: +RECO/ERP/BACKUPSET/2016_02_10/nnndf0_tag20160210t192350_0.297.903468233
  List of Datafiles in backup set 74
  File LV Type Ckp SCN    Ckp Time  Name
  ---- -- ---- ---------- --------- ----
  1       Full 568415     10-FEB-16 +DATA/ERP/DATAFILE/system.307.903310469
  2       Full 568415     10-FEB-16 +DATA/ERP/DATAFILE/sysaux.308.903310481
  3       Full 568415     10-FEB-16 +DATA/ERP/DATAFILE/undotbs1.309.903310489
  4       Full 568415     10-FEB-16 +DATA/ERP/DATAFILE/undotbs2.311.903310505
  5       Full 568415     10-FEB-16 +DATA/ERP/DATAFILE/users.312.903310507
  6       Full 568415     10-FEB-16 +DATA/ERP/DATAFILE/erpdata.322.903467573
  7       Full 568415     10-FEB-16 +DATA/ERP/DATAFILE/erpindx.323.903467623
BS Key  Type LV Size       Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
75      Full    1.05M      DISK        00:00:03     10-FEB-16
        BP Key: 77   Status: AVAILABLE  Compressed: YES  Tag: TAG20160210T192350
        Piece Name: +RECO/ERP/BACKUPSET/2016_02_10/ncsnf0_tag20160210t192350_0.298.903468291
  SPFILE Included: Modification time: 09-FEB-16
  SPFILE db_unique_name: ERP
  Control File Included: Ckp SCN: 568565       Ckp time: 10-FEB-16
BS Key  Type LV Size       Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
92      Full    18.11M     DISK        00:00:02     10-FEB-16
        BP Key: 95   Status: AVAILABLE  Compressed: NO  Tag: TAG20160210T192458
        Piece Name: +RECO/ERP/BACKUPSET/2016_02_10/ncnnf0_tag20160210t192458_0.299.903468301
  Control File Included: Ckp SCN: 568606       Ckp time: 10-FEB-16
BS Key  Type LV Size       Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
103     Full    80.00K     DISK        00:00:00     10-FEB-16
        BP Key: 105   Status: AVAILABLE  Compressed: NO  Tag: TAG20160210T192504
        Piece Name: +RECO/ERP/BACKUPSET/2016_02_10/nnsnf0_tag20160210t192504_0.300.903468305
  SPFILE Included: Modification time: 09-FEB-16
  SPFILE db_unique_name: ERP
BS Key  Size       Device Type Elapsed Time Completion Time
------- ---------- ----------- ------------ ---------------
135     110.95M    DISK        00:00:39     10-FEB-16
        BP Key: 137   Status: AVAILABLE  Compressed: YES  Tag: TAG20160210T192525
        Piece Name: +RECO/ERP/BACKUPSET/2016_02_10/annnf0_tag20160210t192525_0.305.903468329
  List of Archived Logs in backup set 135
  Thrd Seq     Low SCN    Low Time  Next SCN   Next Time
  ---- ------- ---------- --------- ---------- ---------
  1    27      331823     09-FEB-16 372417     09-FEB-16
  1    28      372417     09-FEB-16 423849     09-FEB-16
  1    29      423849     09-FEB-16 486592     09-FEB-16
  1    30      486592     09-FEB-16 530932     10-FEB-16
  1    31      530932     10-FEB-16 568653     10-FEB-16
  1    32      568653     10-FEB-16 568679     10-FEB-16
  2    1       332399     09-FEB-16 332423     09-FEB-16
  2    2       334407     09-FEB-16 404968     09-FEB-16
  2    3       404968     09-FEB-16 468910     09-FEB-16
  2    4       468910     09-FEB-16 478168     09-FEB-16
  2    5       478168     09-FEB-16 486479     09-FEB-16
  2    6       486479     09-FEB-16 506366     10-FEB-16
  2    7       506366     10-FEB-16 547162     10-FEB-16
  2    8       547162     10-FEB-16 568657     10-FEB-16
  2    9       568657     10-FEB-16 568683     10-FEB-16
RMAN>

Nesse laboratório o SCN para ser usado no duplicate é o 568679, pois entre os maiores Next SCN das duas threads existentes, ele é o menor.

[oracle@ol7db01 ~]$ rman target sys/OraLin2016@erp auxiliary sys/OraLin2016@clone catalog rman/server@rcat
Recovery Manager: Release 12.1.0.2.0 - Production on Wed Feb 10 21:46:52 2016
Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.
connected to target database: ERP (DBID=152032381)
connected to recovery catalog database
connected to auxiliary database: CLONE (not mounted)
RMAN> run
{
allocate channel c1 device type disk;
allocate auxiliary channel d1 device type disk;
set until scn 568679;
DUPLICATE TARGET DATABASE TO "clone";
}

Nota: Na versão 12c (12.1.0.2) existe um bug [Bug 20977794 – RMAN-3002 … ORA-65500 from RMAN duplicate on RAC (Doc ID 20977794.8)] que faz com que o comando acima gere o erro abaixo e seja impossível prosseguir com a duplicação do database. Esse erro ocorre quando o RMAN tenta alterar o parametro db_unique_name do database de destino (clone). Esse bug afeta apenas databases que utilizam o Grid Infraestructure. Caso esteja usando como destino um database Single Instance não enfrentará esse erro. Já existe um patch [Patch 20977794: RMAN DUPLICATE ERROR: ORA-65500: COULD NOT MODIFY DB_UNIQUE_NAME, RESOURCE EXIST] para esse bug, mas caso você não possa aplicá-lo agora, vou colocar em seguida um workaround.

Starting Duplicate Db at 10-FEB-16
contents of Memory Script:
{
   set until scn  568679;
   sql clone "alter system set  control_files =
  ''+DATA/CLONE/CONTROLFILE/current.289.903412809'', ''+RECO/CLONE/CONTROLFILE/current.287.903412809'' comment=
 ''Set by RMAN'' scope=spfile";
   sql clone "alter system set  db_name =
 ''ERP'' comment=
 ''Modified by RMAN duplicate'' scope=spfile";
   sql clone "alter system set  db_unique_name =
 ''CLONE'' comment=
 ''Modified by RMAN duplicate'' scope=spfile";
   shutdown clone immediate;
   startup clone force nomount
   restore clone primary controlfile;
   alter clone database mount;
}
executing Memory Script
executing command: SET until clause
sql statement: alter system set  control_files =   ''+DATA/CLONE/CONTROLFILE/current.289.903412809'', ''+RECO/CLONE/CONTROLFILE/current.287.903412809'' comment= ''Set by RMAN'' scope=spfile
sql statement: alter system set  db_name =  ''ERP'' comment= ''Modified by RMAN duplicate'' scope=spfile
sql statement: alter system set  db_unique_name =  ''CLONE'' comment= ''Modified by RMAN duplicate'' scope=spfile
released channel: c1
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of Duplicate Db command at 02/14/2016 20:06:41
RMAN-04014: startup failed: ORA-00304: requested INSTANCE_NUMBER is busy
RMAN-03015: error occurred in stored script Memory Script
RMAN-03009: failure of sql command on clone_default channel at 02/14/2016 20:06:17
RMAN-11003: failure during parse/execution of SQL statement: alter system set  db_unique_name =  'CLONE' comment= 'Modified by RMAN duplicate' scope=spfile
ORA-32017: failure in updating SPFILE
ORA-65500: could not modify DB_UNIQUE_NAME, resource exists

Se você está enfrentando o bug da versão 12.1.0.2, como foi o meu caso neste lab, e não pode aplicar o patch de correção, será necessário realizar as seguintes atividades adicionais.

Remover o database do Grid Infraestructure.

[oracle@ol7db01 ~]$ srvctl remove database -db clone

Realizar o clone confirme o comando já indicado anteriormente.

Starting Duplicate Db at 14-FEB-16
contents of Memory Script:
{
   set until scn  568679;
   sql clone "alter system set  control_files =
  ''+DATA/CLONE/CONTROLFILE/current.289.903412809'', ''+RECO/CLONE/CONTROLFILE/current.287.903412809'' comment=
 ''Set by RMAN'' scope=spfile";
   sql clone "alter system set  db_name =
 ''ERP'' comment=
 ''Modified by RMAN duplicate'' scope=spfile";
   sql clone "alter system set  db_unique_name =
 ''CLONE'' comment=
 ''Modified by RMAN duplicate'' scope=spfile";
   shutdown clone immediate;
   startup clone force nomount
   restore clone primary controlfile;
   alter clone database mount;
}
executing Memory Script
executing command: SET until clause
sql statement: alter system set  control_files =   ''+DATA/CLONE/CONTROLFILE/current.289.903412809'', ''+RECO/CLONE/CONTROLFILE/current.287.903412809'' comment= ''Set by RMAN'' scope=spfile
sql statement: alter system set  db_name =  ''ERP'' comment= ''Modified by RMAN duplicate'' scope=spfile
sql statement: alter system set  db_unique_name =  ''CLONE'' comment= ''Modified by RMAN duplicate'' scope=spfile
Oracle instance shut down
Oracle instance started
Total System Global Area    1073741824 bytes
Fixed Size                     2932632 bytes
Variable Size                763363432 bytes
Database Buffers             301989888 bytes
Redo Buffers                   5455872 bytes
allocated channel: d1
channel d1: SID=9 device type=DISK
Starting restore at 14-FEB-16
channel d1: starting datafile backup set restore
channel d1: restoring control file
channel d1: reading from backup piece +RECO/ERP/BACKUPSET/2016_02_10/ncnnf0_tag20160210t192458_0.299.903468301
channel d1: piece handle=+RECO/ERP/BACKUPSET/2016_02_10/ncnnf0_tag20160210t192458_0.299.903468301 tag=TAG20160210T192458
channel d1: restored backup piece 1
channel d1: restore complete, elapsed time: 00:00:04
output file name=+DATA/CLONE/CONTROLFILE/current.289.903412809
output file name=+RECO/CLONE/CONTROLFILE/current.287.903412809
Finished restore at 14-FEB-16
database mounted
contents of Memory Script:
{
   set until scn  568679;
   set newname for clone datafile  1 to new;
   set newname for clone datafile  2 to new;
   set newname for clone datafile  3 to new;
   set newname for clone datafile  4 to new;
   set newname for clone datafile  5 to new;
   set newname for clone datafile  6 to new;
   set newname for clone datafile  7 to new;
   restore
   clone database
   ;
}
executing Memory Script
executing command: SET until clause
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
Starting restore at 14-FEB-16
channel d1: starting datafile backup set restore
channel d1: specifying datafile(s) to restore from backup set
channel d1: restoring datafile 00001 to +DATA
channel d1: restoring datafile 00002 to +DATA
channel d1: restoring datafile 00003 to +DATA
channel d1: restoring datafile 00004 to +DATA
channel d1: restoring datafile 00005 to +DATA
channel d1: restoring datafile 00006 to +DATA
channel d1: restoring datafile 00007 to +DATA
channel d1: reading from backup piece +RECO/ERP/BACKUPSET/2016_02_10/nnndf0_tag20160210t192350_0.297.903468233
channel d1: piece handle=+RECO/ERP/BACKUPSET/2016_02_10/nnndf0_tag20160210t192350_0.297.903468233 tag=TAG20160210T192350
channel d1: restored backup piece 1
channel d1: restore complete, elapsed time: 00:01:16
Finished restore at 14-FEB-16
contents of Memory Script:
{
   switch clone datafile all;
}
executing Memory Script
datafile 1 switched to datafile copy
input datafile copy RECID=8 STAMP=903818222 file name=+DATA/CLONE/DATAFILE/system.325.903818147
datafile 2 switched to datafile copy
input datafile copy RECID=9 STAMP=903818222 file name=+DATA/CLONE/DATAFILE/sysaux.326.903818147
datafile 3 switched to datafile copy
input datafile copy RECID=10 STAMP=903818223 file name=+DATA/CLONE/DATAFILE/undotbs1.327.903818147
datafile 4 switched to datafile copy
input datafile copy RECID=11 STAMP=903818223 file name=+DATA/CLONE/DATAFILE/undotbs2.328.903818147
datafile 5 switched to datafile copy
input datafile copy RECID=12 STAMP=903818223 file name=+DATA/CLONE/DATAFILE/users.331.903818149
datafile 6 switched to datafile copy
input datafile copy RECID=13 STAMP=903818223 file name=+DATA/CLONE/DATAFILE/erpdata.329.903818149
datafile 7 switched to datafile copy
input datafile copy RECID=14 STAMP=903818223 file name=+DATA/CLONE/DATAFILE/erpindx.330.903818149
contents of Memory Script:
{
   set until scn  568679;
   recover
   clone database
    delete archivelog
   ;
}
executing Memory Script
executing command: SET until clause
Starting recover at 14-FEB-16
starting media recovery
channel d1: starting archived log restore to default destination
channel d1: restoring archived log
archived log thread=1 sequence=31
channel d1: restoring archived log
archived log thread=2 sequence=8
channel d1: restoring archived log
archived log thread=1 sequence=32
channel d1: restoring archived log
archived log thread=2 sequence=9
channel d1: reading from backup piece +RECO/ERP/BACKUPSET/2016_02_10/annnf0_tag20160210t192525_0.305.903468329
channel d1: piece handle=+RECO/ERP/BACKUPSET/2016_02_10/annnf0_tag20160210t192525_0.305.903468329 tag=TAG20160210T192525
channel d1: restored backup piece 1
channel d1: restore complete, elapsed time: 00:00:47
archived log file name=+RECO/CLONE/ARCHIVELOG/2016_02_14/thread_2_seq_8.309.903818257 thread=2 sequence=8
archived log file name=+RECO/CLONE/ARCHIVELOG/2016_02_14/thread_1_seq_31.308.903818257 thread=1 sequence=31
channel clone_default: deleting archived log(s)
archived log file name=+RECO/CLONE/ARCHIVELOG/2016_02_14/thread_1_seq_31.308.903818257 RECID=15 STAMP=903818267
archived log file name=+RECO/CLONE/ARCHIVELOG/2016_02_14/thread_1_seq_32.310.903818257 thread=1 sequence=32
channel clone_default: deleting archived log(s)
archived log file name=+RECO/CLONE/ARCHIVELOG/2016_02_14/thread_2_seq_8.309.903818257 RECID=14 STAMP=903818264
archived log file name=+RECO/CLONE/ARCHIVELOG/2016_02_14/thread_2_seq_9.311.903818257 thread=2 sequence=9
channel clone_default: deleting archived log(s)
archived log file name=+RECO/CLONE/ARCHIVELOG/2016_02_14/thread_1_seq_32.310.903818257 RECID=12 STAMP=903818257
channel clone_default: deleting archived log(s)
archived log file name=+RECO/CLONE/ARCHIVELOG/2016_02_14/thread_2_seq_9.311.903818257 RECID=13 STAMP=903818257
media recovery complete, elapsed time: 00:00:03
Finished recover at 14-FEB-16
Oracle instance started
Total System Global Area    1073741824 bytes
Fixed Size                     2932632 bytes
Variable Size                763363432 bytes
Database Buffers             301989888 bytes
Redo Buffers                   5455872 bytes
contents of Memory Script:
{
   sql clone "alter system set  db_name =
 ''CLONE'' comment=
 ''Reset to original value by RMAN'' scope=spfile";
   sql clone "alter system reset  db_unique_name scope=spfile";
}
executing Memory Script
sql statement: alter system set  db_name =  ''CLONE'' comment= ''Reset to original value by RMAN'' scope=spfile
sql statement: alter system reset  db_unique_name scope=spfile
Oracle instance started
Total System Global Area    1073741824 bytes
Fixed Size                     2932632 bytes
Variable Size                763363432 bytes
Database Buffers             301989888 bytes
Redo Buffers                   5455872 bytes
sql statement: CREATE CONTROLFILE REUSE SET DATABASE "CLONE" RESETLOGS ARCHIVELOG
  MAXLOGFILES    192
  MAXLOGMEMBERS      3
  MAXDATAFILES     1024
  MAXINSTANCES    32
  MAXLOGHISTORY      292
 LOGFILE
  GROUP   1  SIZE 50 M ,
  GROUP   2  SIZE 50 M
 DATAFILE
  '+DATA/CLONE/DATAFILE/system.325.903818147'
 CHARACTER SET WE8MSWIN1252
sql statement: ALTER DATABASE ADD LOGFILE
  INSTANCE 'i2'
  GROUP   3  SIZE 50 M ,
  GROUP   4  SIZE 50 M
contents of Memory Script:
{
   set newname for clone tempfile  1 to new;
   switch clone tempfile all;
   catalog clone datafilecopy  "+DATA/CLONE/DATAFILE/sysaux.326.903818147",
 "+DATA/CLONE/DATAFILE/undotbs1.327.903818147",
 "+DATA/CLONE/DATAFILE/undotbs2.328.903818147",
 "+DATA/CLONE/DATAFILE/users.331.903818149",
 "+DATA/CLONE/DATAFILE/erpdata.329.903818149",
 "+DATA/CLONE/DATAFILE/erpindx.330.903818149";
   switch clone datafile all;
}
executing Memory Script
executing command: SET NEWNAME
renamed tempfile 1 to +DATA in control file
cataloged datafile copy
datafile copy file name=+DATA/CLONE/DATAFILE/sysaux.326.903818147 RECID=1 STAMP=903818319
cataloged datafile copy
datafile copy file name=+DATA/CLONE/DATAFILE/undotbs1.327.903818147 RECID=2 STAMP=903818320
cataloged datafile copy
datafile copy file name=+DATA/CLONE/DATAFILE/undotbs2.328.903818147 RECID=3 STAMP=903818320
cataloged datafile copy
datafile copy file name=+DATA/CLONE/DATAFILE/users.331.903818149 RECID=4 STAMP=903818320
cataloged datafile copy
datafile copy file name=+DATA/CLONE/DATAFILE/erpdata.329.903818149 RECID=5 STAMP=903818320
cataloged datafile copy
datafile copy file name=+DATA/CLONE/DATAFILE/erpindx.330.903818149 RECID=6 STAMP=903818321
datafile 2 switched to datafile copy
input datafile copy RECID=1 STAMP=903818319 file name=+DATA/CLONE/DATAFILE/sysaux.326.903818147
datafile 3 switched to datafile copy
input datafile copy RECID=2 STAMP=903818320 file name=+DATA/CLONE/DATAFILE/undotbs1.327.903818147
datafile 4 switched to datafile copy
input datafile copy RECID=3 STAMP=903818320 file name=+DATA/CLONE/DATAFILE/undotbs2.328.903818147
datafile 5 switched to datafile copy
input datafile copy RECID=4 STAMP=903818320 file name=+DATA/CLONE/DATAFILE/users.331.903818149
datafile 6 switched to datafile copy
input datafile copy RECID=5 STAMP=903818320 file name=+DATA/CLONE/DATAFILE/erpdata.329.903818149
datafile 7 switched to datafile copy
input datafile copy RECID=6 STAMP=903818321 file name=+DATA/CLONE/DATAFILE/erpindx.330.903818149
contents of Memory Script:
{
   Alter clone database open resetlogs;
}
executing Memory Script
database opened
Finished Duplicate Db at 14-FEB-16

Depois do clone concluído, adicionar novamente o database ao Grid Infraestructure.

[oracle@ol7db01 ~]$ srvctl add database -db clone -oraclehome /u01/app/oracle/product/12.1.0/dbhome_1 -dbtype raconenode -server ol7db01 -spfile +DATA/clone/spfileclone.ora -pwfile /u01/app/oracle/product/12.1.0/dbhome_1/dbs/orapwclone -diskgroup DATA,RECO

Agora o database de origem (erp) está duplicado no database de destino (clone). Você pode remover/reconfigurar, se quiser, os parâmetros que adicionou/alterou no listener.ora e no tnsnames.ora.

Conectar em Instâncias BLOCKED ou RESTRICTED via listener

Eventualmente você pode se deparar com a seguinte mensagem de erro:

ORA-12528: TNS:listener: all appropriate instances are blocking new connections

Essa mensagem ocorre quando você está tentando conectar via listener em um database que foi colocado no estado RESTRICTED ou que foi iniciado no modo NOMOUNT.

Obs.: Esse erro não ocorre se você conectar localmente ao database usando o protocolo bequeath (BEQ), ou seja, quando conecta usando “# sqlplus /”, pois nessa situação você não está usando o listener. Nas conexões locais o próprio client (sqlplus) realiza um fork no dedicated process do Oracle e estabelece uma comunicação com ele usando 2 pipes, um para escrita e outro para leitura. Essencialmente é a mesma ação que seria realizada pelo listener para atender uma solicitação de conexão.

Esse erro é comum de ocorrer quando está clonando um database devido à necessidade de fazer o RMAN conectar no database “auxiliary” enquanto este está no modo NOMOUNT.

Para resolver esse problema basta alterar o tnsnames.ora e adicionar o parâmetro UR = A na sessão CONNECT_DATA da referida entrada. Segue exemplo abaixo.

DBCLONE1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = dbserver.domain.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = dbclone1)
      (UR = A)
    )
  )

Esse parâmetro foi criado como resposta à uma solicitação de aprimoramento. Ele serve para permitir que usuários administrativos ou privilegiados possam conectar via listener mesmo quando as conexões de usuários não-privilegiados estão bloqueadas.

Parâmetro disponível a partir da versão 10g.

Configurar Instâncias Oracle com Linux HugePages

Os Sistemas Operacionais Linux possuem uma funcionalidade muito interessante chamada de HugePages, que quando usada por um banco Oracle oferece grandes ganhos de performance.

HugePages consiste em tornar os blocos de alocação de memória muito maiores do que os 4KB padrão. No Linux os HugePages possuem 2MB por padrão. Outra vantagem é que os HugePages são sempre alocados na memória física e nunca vão para a área de swap. Na verdade esses blocos de memória sequer são considerados como candidatos a ir para swap.

Configuração

A primeira coisa a ser feita para a configuração é identificar quanta quantidade de memória você necessita para ser usada como HugePages. No caso de uma instância Oracle você deve alocar uma quantidade de memória suficiente para acomodar todo o seu SGA. Para isso use a fórmula abaixo.

X = Y / Z

Onde:

X: Quantidade de HugePages necessárias
Y: Tamanho do seu SGA também em KB
Z: Tamanho do HugePage em KB

Obs.: Uma dica é sempre configurar um valor um pouco maior do informado na fórmula. Eu normalmente somo 8 no resultado encontrado.

Agora que você já sabe o número de HugePages que deve configurar, vamos colocar a mão na massa!

Configurando o Linux

O primeiro passo é editar o arquivo /etc/sysctl.conf e adicionar os seguintes parâmetros:

vm.nr_hugepages=<Número de HugePages>
vm.hugetlb_shm_group=<ID do grupo principal do usuário oracle>

Para verificar o ID do grupo principal (gid) do usuário oracle utilize o comando id:

# id oracle
uid=500(oracle) gid=501(oinstall) groups=501(oinstall),500(dba)

No exemplo acima o ID é 501.

O passo seguinte é editar o arquivo /etc/security/limits.conf e definir a quantidade máxima de memória que o usuário oracle pode alocar:

oracle     soft    memlock  8404992 oracle     hard    memlock  8404992

O valor deve ser informado em KB e ser maior que o SGA.

Depois de configurar esses parâmetros reinicie o S.O. para que as configurações entrem em vigor. Para validar use os seguintes comandos:

# cat /proc/meminfo
MemTotal:       264234552 kB
MemFree:        10208592 kB
Buffers:          924660 kB
Cached:         103365808 kB
SwapCached:        74752 kB
Active:         61245124 kB
Inactive:       66576684 kB
Active(anon):   56581924 kB
Inactive(anon):  5085572 kB
Active(file):    4663200 kB
Inactive(file): 61491112 kB
Unevictable:      347136 kB
Mlocked:          347136 kB
SwapTotal:      25165820 kB
SwapFree:       24892344 kB
Dirty:              4444 kB
Writeback:             0 kB
AnonPages:      24014904 kB
Mapped:         23040796 kB
Shmem:          37860316 kB
Slab:            1418188 kB
SReclaimable:     958620 kB
SUnreclaim:       459568 kB
KernelStack:       26880 kB
PageTables:      1871460 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    97907480 kB
Committed_AS:   78301368 kB
VmallocTotal:   34359738367 kB
VmallocUsed:     1053720 kB
VmallocChunk:   34358648516 kB
HardwareCorrupted:     0 kB
HugePages_Total:   57984
HugePages_Free:     5085
HugePages_Rsvd:     5082
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        6144 kB
DirectMap2M:     2082816 kB
DirectMap1G:    266338304 kB

Verifique se o item de HugePages_Total está com o valor configurado.

Para validar o limite de alocação de memória do usuário oracle, logue-se com ele e use o comando abaixo:

# ulimit -l

Verifique se o valor retornado é igual ao configurado.

Agora basta configurar o Oracle.

Configurando o Oracle

No Oracle é necessário desabilitar o Automatic Memory Management (AMM). Esse recurso que simplifica o gerenciamento de memória da instância, ajustando automaticamente os tamanhos da SGA e da PGA, não é compatível com HugePages.

Nota: O AMM foi introduzido na versão 11g, portanto se você está configurando uma versão anterior não precisa se preocupar com ele.

Para desabilitar o AMM, basta desconfigurar os parâmetros MEMORY_TARGET e MEMORY_MAX_TARGET, e configurar o SGA_TARGET, SGA_MAX_SIZE e PGA_AGGREGATE_TARGET.

SQL> show parameter target;
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
archive_lag_target                   integer     0
db_flashback_retention_target        integer     1440
fast_start_io_target                 integer     0
fast_start_mttr_target               integer     300
memory_max_target                    big integer 0
memory_target                        big integer 0
parallel_servers_target              integer     240
pga_aggregate_target                 big integer 6G
sga_target                           big integer 24G
SQL> show parameter sga
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
lock_sga                             boolean     FALSE
pre_page_sga                         boolean     FALSE
sga_max_size                         big integer 24G
sga_target                           big integer 24G

Se estiver usando uma versão de banco anterior à 11.2.0.3, precisa ter atenção redobrada na hora de configurar a quantidade/tamanho de HugePages, pois nessas versões não existe uso parcial de HugePages. Ou seja, versões até 11.2.0.2 tentam colocar a SGA inteira em HugePages, caso a quantidade não seja suficiente, a SGA será alocada integralmente em páginas normais.

A partir da versão 11.2.0.3 passa ser possível colocar apenas parte da SGA em HugePages, e a parte que sobrar é alocada em páginas regulares. Por exemplo, caso sua SGA seja de 32GB e o número de HugePages configurado some apenas 20GB, os 12GB excedentes serão alocados em páginas regulares.

Para verificar se a instancia iniciou usando corretamente as HugePages olhe o Alert log, conforme abaixo.

Starting ORACLE instance (normal)
****************** Large Pages Information *****************
Total Shared Global Region in Large Pages = 24 GB (100%)
Large Pages used by this instance: 12289 (24 GB)
Large Pages unused system wide = 3 (6144 KB) (alloc incr 64 MB)
Large Pages configured system wide = 57984 (113 GB)
Large Page size = 2048 KB
***********************************************************

Para facilitar o controle sobre quando a instância iniciou usando corretamente as HugePages e evitar que algo errado aconteça e somente seja percebido posteriormente, quando o banco estiver apresentando problemas de performance, na versão 11.2.0.2 foi criado o parâmetro USE_LARGE_PAGES.

Esse parâmetro poder ter os seguintes valores TRUE, FALSE e ONLY.

  • FALSE a instância nunca usará as HugePages.
  • TRUE a instância tentará usar as HugePages conforme descrito acima, podendo ser afetada pela configuração incorreta do número de HugePages e alocando a SGA de forma parcial ou total em páginas regulares.
  • ONLY a instância tentará alocar toda a SGA em HugePages, caso não consiga será gerado um erro e a instância não iniciará.

O erro gerado pelo parâmetro USE_LARGE_PAGES=ONLY é o seguinte:

SQL> startup
ORA-27137: unable to allocate large pages to create a shared memory segment
Linux-x86_64 Error: 12: Cannot allocate memory

Essa situação também pode ser verificada no Alert log.

****************** Large Pages Information *****************
Parameter use_large_pages = ONLY

Large Pages unused system wide = 0 (0 KB) (alloc incr 4096 KB)
Large Pages configured system wide = 0 (0 KB)
Large Page size = 2048 KB

ERROR:
  Failed to allocate shared global region with large pages, unix errno = 12.
  Aborting Instance startup.
  ORA-27137: unable to allocate Large Pages to create a shared memory segment

ACTION:
  Total Shared Global Region size is 24 GB. Increase the number of
  unused large pages to atleast 12289 (24 GB) to allocate 100% Shared Global
  Region with Large Pages.
***********************************************************

Usando esse parâmetro, você pode ter certeza que quando a instância inicia ela está efetivamente carregada em HugePages.

Criar ASM Diskgroups dentro de volumes NFS

Neste artigo vou abordar a utilização de arquivos em volumes NFS como discos ASM.
A ideia dessa configuração surgiu da minha necessidade de montar um ambiente de laboratório com Oracle 12c em RAC usando o Hyper-V do meu notebook.
Como o Hyper-V não suporta (até o momento em que este post foi criado, em 2016) o compartilhamento de discos entre VMs quando usados apenas discos locais, foi necessário buscar um método alternativo para criar o ambiente. Dessa forma, além das duas máquinas virtuais para os hosts do RAC, criei mais uma para ser o servidor NFS.

Nota: Apesar da utilização de arquivos em volumes NFS como discos ASM ser uma configuração suportada pela Oracle, ela deve ser utilizada com muita cautela, principalmente se pretende usá-la em produção. A utilização de volumes NFS requer a montagem no modo “hard”, o que faz com que a instância ASM ou o Database esperem indefinidamente por uma resposta do servidor NFS quando este ficar indisponível. Isso significa que o ASM não poderá fornecer de forma efetiva o espelhamento de dados.
De uma forma geral, para usar essa configuração os Diskgroups devem ser configurados com redundância “External” e a comunicação com os volumes NFS deve ser confiável.
Ref.:  How To Create ASM Diskgroups using NFS/NAS Files? (Doc ID 731775.1)

Configurando o servidor NFS (O Storage)

No ambiente de laboratório que estou montando o SO usado é o Oracle Linux 7, portanto todos os comandos aqui são relativos a essa versão, que trouxe varias novidades em relação ao Oracle Linux 6, principalmente a adição do systemd como mecanismo de controle e gerenciamento de serviços, devices, sockets e pontos de montagem.

Primeiramente instale o servidor NFS.

[root@ol7nfs01 ~]# yum install nfs-utils

Crie o diretório onde serão colocados os arquivos que serão usados como discos pelo ASM

[root@ol7nfs01 ~]# mkdir /nfs

Edite o arquivo /etc/exports para configurar a publicação do diretório pelo servidor NFS. Tenha atenção aos parâmetros usados e somente altere-os se souber o que está fazendo. Nesse laboratório o diretório que estou exportando é o “/nfs”.

[root@ol7nfs01 ~]# cat /etc/exports
/nfs    *(rw,sync,no_wdelay,insecure_locks,no_root_squash)

Inicie e ative o serviço do NFS, para que o mesmo inicie sempre que o servidor reiniciar.

[root@ol7nfs01 ~]# systemctl start nfs-server
[root@ol7nfs01 ~]# systemctl enable nfs-server

Configurando o cliente NFS (O Database Server)

A primeira atividade nos servidores de banco que montarão o diretório NFS é criar a pasta que servirá de ponto de montagem.

[root@ol7db01 ~]# mkdir -p /u01/oradata

Em seguida edite o arquivo /etc/fstab para que o volume NFS seja montado sempre que o servidor for reiniciado. Adicione a seguinte linha ao fstab, sendo que “ol7nfs01” é o nome do servidor NFS. Novamente atenção aos parâmetros e somente altere-os se souber o que está fazendo.

ol7nfs01:/nfs    /u01/oradata    nfs     rw,bg,hard,nointr,tcp,vers=3,timeo=600,rsize=32768,wsize=32768,actimeo=0  0 0

Agora você pode montar o volume NFS

[root@ol7db01 ~]# mount -a

Em seguida configure o “ownership” e as permissões do diretório. Estou assumindo que o usuário oracle e o grupo oinstall já estão criados.

[root@ol7db01 ~]# chown -R oracle:oinstall /u01/oradata
[root@ol7db01 ~]# chmod -R 775 /u01/oradata

O próximo passo é criar os arquivos que serão usados como discos para o ASM. Vou criar alguns arquivos de 10 GB para usar nos diskgroups DATA e RECO. Como no meu laboratório vou instalar o Grid Infrastructure sob o usuário grid, usarei ele para criar os arquivos.

[grid@ol7db01 ~]$ mkdir /u01/oradata/asm
[grid@ol7db01 ~]$ dd if=/dev/zero of=/u01/oradata/asm/data01.disk bs=1k count=10000000
[grid@ol7db01 ~]$ dd if=/dev/zero of=/u01/oradata/asm/data02.disk bs=1k count=10000000
[grid@ol7db01 ~]$ dd if=/dev/zero of=/u01/oradata/asm/data03.disk bs=1k count=10000000
[grid@ol7db01 ~]$ dd if=/dev/zero of=/u01/oradata/asm/data04.disk bs=1k count=10000000
[grid@ol7db01 ~]$ dd if=/dev/zero of=/u01/oradata/asm/data05.disk bs=1k count=10000000
[grid@ol7db01 ~]$ dd if=/dev/zero of=/u01/oradata/asm/reco01.disk bs=1k count=10000000
[grid@ol7db01 ~]$ dd if=/dev/zero of=/u01/oradata/asm/reco02.disk bs=1k count=10000000

Devemos ajustar novamente as permissões no diretório e arquivos criados.

[grid@ol7db01 ~]$ chmod 775 /u01/oradata/asm
[grid@ol7db01 ~]$ chmod 664 /u01/oradata/asm/*

Agora o ambiente já está preparado e podemos iniciar a instalação do Grid Infrastructure. Na tela de criação do diskgroup do ASM inicialmente não vão aparecer os discos candidatos. Basta clicar em “Change Discovery Path” e indicar o diretório NFS onde foram criados os arquivos.

Na tela para alterar o caminho de descoberta dos discos, digite o caminho com o asterisco como caractere coringa.

Quando retornar à tela de seleção de discos, os arquivos aparecerão listados.

Deste ponto em diante o processo é exatamente igual à qualquer instalação do Grid Infrastructure.

Converter um certificado PEM/CRT + KEY para PFX

Para converter um certificado que está no formato PEM/CRT juntamente com o arquivo de chave privada (KEY) em um arquivo PFX que pode ser usado de forma mais simplificada em ambientes Windows/IIS, precisamos do OpenSSL.

O comando abaixo faz a mágica.

# openssl pkcs12 -export -out certificado.pfx -inkey privateKey.key -in certificado.pem -certfile CACert.crt

Onde:
– certificado.pfx: arquivo a ser gerado.
– certificado.pem: arquivo com o certificado no formato PEM. Pode estar com a extensão .crt também.
– privateKey.key: arquivo com a chave privada do certificado.
– CAcert.crt: arquivo com o certificado da entidade certificadora e os certificados intermediários. Este item não é obrigatório.

Obs.: um erro que costuma ocorrer é quando algum dos arquivos de entrada estão codificados com UTF8 BOM. O OpenSSL não consegue ler corretamente esse formato. Nesse caso edite o arquivo com algum editor de texto avançado, como o Notepad++, e altere a codificação para UTF8.

Configurando Proxy Reverso para Websocket no Apache

Em um post anterior mostramos como configurar o Apache como um Proxy Reverso, permitindo publicar sites hospedados em um servidor interno ou em sua DMZ externamente, sem expor diretamente esse servidor para acessos externos.

No entanto, caso a aplicação web hospedada no servidor de backend utilize o protocolo Websocket para manter uma conexão permanente entre cliente e servidor, são necessárias algumas configurações adicionais.

Basicamente, para que o Apache possa fazer corretamente o Proxy desse protocolo, é necessário utilizar o RewriteEngine para que quando seja identificado no cabeçalho HTTP enviado pelo cliente uma solicitação de “Upgrade” para Websocket, seja realizada a reescrita da requisição usando o endereço do servidor backend da aplicação.

RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) "wss://localhost:8443%{REQUEST_URI}" [P,L]

As condições acima fazem simplesmente identificar no cabeçalho se os campos Upgrade e Connection foram definidos conforme a RFC que define o protocolo Websocket e faz a reescrita da URL da Request, trocando a parte do Host pelo endereço do servidor interno. No caso desse exemplo acima, o servidor de backend está no mesmo Host (localhost) mas em outra porta (8443).

Configurando Proxy Reverso no Apache

Existem diversas situações que podem requerer a configuração de um proxy reverso. As mais comuns que encontramos no nosso dia-a-dia são para criar uma camada adicional de proteção para um servidor que pode estar rodando um software mais antigo e não apresentar nível de segurança suficiente para ficar exposto na internet.

Outra situação é configurar um balanceamento de carga entre servidores de aplicação, ficando o proxy reverso na função de centralizar as conexões e distribuí-las para os servidores de aplicação disponíveis.

A configuração mais simples é a que possui apenas um servidor de aplicação como backend sendo acessado pelo proxy reverso. Sua configuração requer apenas as instruções abaixo.

ProxyPass "/" "http://localhost:8080/"
ProxyPassReverse "/" "http://localhost:8080/"

Essas instruções devem, preferencialmente, estar dentro de um VirtualHost, para evitar confusões com outros sites que o Apache possa estar servindo. Mas caso seja um servidor usado apenas para o proxy reverso de um site apenas, é possível colocar na sessão principal do httpd.conf.

O que essa instrução faz é passar todas as requisições para o backend. No entanto, é possível fazer proxy apenas de determinadas pastas.

ProxyPass "/imagens/" "http://localhost:8080/imagens/"
ProxyPassReverse "/imagens/" "http://localhost:8080/imagens/"

Nesse exemplo acima, no caso de uma requisição para http://www.exemplo.com.br/imagens/logo.png seria feito o proxy para o serviço rodando na porta 8080, mas uma requisição para http://www.exemplo.com.br/index.php seria servido pelo próprio Apache local.

Uma questão importante é que os diretórios do proxy e do backend não precisam ser sempre iguais.

ProxyPass "/" "http://localhost:8080/site/"
ProxyPassReverse "/" "http://localhost:8080/site/"

Nas instruções acima, um acesso ao endereço http://www.exemplo.com.br/index.php seria direcionado para o backend no caminho http://localhost:8080/site/index.php

Isso é bastante útil e permite inclusive que caminhos diferentes da URL sejam servidos por servidores backend diferentes.

Atualizando Hosts Standalone do VMware ESXi

Quando se está utilizando o VMware ESXi como virtualizador sem o auxilio do vCenter para fazer a gestão, o processo de atualização e aplicação de patches pode ser um pouco complicada. Nesse post vou mostrar duas formas de fazer essa atualização.

As duas formas precisam ser executadas via linha de comando no host, portanto habilite o acesso SSH no ESXi antes de iniciar.

Também é necessário que o host esteja em modo de manutenção e todas as VMs desligadas.

A primeira forma, que teoricamente é a mais simples, envolve atualizar automaticamente baseado no profile do host.

Identifique a versão atual do VMware ESXi:

# esxcli system version get

Depois verifique qual o Image Profile do Host:

# esxcli software profile get

Habilite o acesso internet a partir do host ESXi, liberando nas regras de firewall local. Caso necessário, libere também o acesso no seu firewall de borda.

# esxcli network firewall ruleset set -e true -r httpClient

Para atualizar o ESXi a partir do repositório online, utilize o comando abaixo:

# esxcli software profile update -d https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml -p ESXi-6.7.0-20190402001-standard

Onde o parâmetro “-p” especifica o Image Profile que foi identificado no passo anterior.

O segundo modo é semelhante, mas ao invés de fazer a atualização a partir do repositório remoto, deve-se primeiro baixar o arquivo (bundle) de atualização e aplicá-lo.

Depois de baixar, coloque o arquivo .zip do bundle de atualização em um datastore do host e utilize o comando de “vib update” passando no parâmetro “-d” o caminho do arquivo de bundle.

# esxcli software vib update -d /vmfs/volumes/5cb37c65-0d32cf9e-7ed2-984be1791ea8/VIB/ESXi670-202004002.zip

Depois da atualização deverá ser realizado um reboot no host.