Quando trabalhamos com o Oracle Fleet Patching and Provioning (FPP), a forma de interação mais simples e direta é através da linha de comando com o utilitário rhpctl. É através dele que damos os primeiros passos com a ferramenta ou realizamos operações administrativas. Para grandes ambientes, existe a possibilidade de integrar com o Oracle Enterprise Manager Cloud Control, o que permite um gerenciamento simplificado com ajuda da interface gráfica mais amigável.

Além dessa integração nativa com o Enteprise Manager nas versões mais recentes, o FPP também possui uma API nativa que possibilita a interação via REST API, usando JSON como formato padrão para interação entre uma aplicação terceira e o FPP. A grande vantagem é a possibilidade de criar integrações e automações com um fluxo customizado, sem necessariamente depender do Enterprise Manager.

Um exemplo de caso de uso é a integração com alguma outra ferramenta de automação que interpreta uma requisição de mudança na ferramenta de ITSM, e dispara um fluxo automático usando o FPP para aplicar patch no servidor de banco de dados de forma autônoma.

Neste post apresento a configuração básica necessária do lado do FPP Server para habilitar este recurso, e alguns exemplos de como realizar operações comuns como provisionar WorkingCopy e mover o Grid ou Database para o novo Oracle Home. Para essa demonstração, os exemplos serão realizados usando o Curl para testes rápidos a partir de qualquer máquina Linux, e ao final demonstro como realizar requisiações através do Postman, que oferece uma interface gráfica e amigável para testar requisições REST, sendo uma ferramenta gratuíta disponível para Windows, Mac e Linux.

Sobre a API

O recurso de REST API do FPP tem uma documentação própria denominada “REST API for Fleet Patching and Provisioning“, e na data de publicação desse post está disponível para as versões 19c e 21c.

Apesar de não suportar todas as operações que são possíveis de se executar via linha de comando, destacto que referente ao que já é possível realizar via API, a documentação é bem completa, clara e objetiva sobre a forma de usar cada opção.

Abaixo a descrição dos métodos suportados pela API:

Se você já conhece um pouco sobre a ferramenta, essa descrição acima com conceitos específicos de REST API, basicamente é equivalente ao seguinte dentro do FPP:

MétodoDescrição
DELETEDeleta uma GoldImage ou uma WorkingCopy
GETRetorna informações sobre uma GoldImage, WorkingCopy ou sobre um JOB
POSTCria uma GoldImage ou uma WorkingCopy
PUTExecuta upgrade de versão de um Oracle Grid ou Oracle Database
PATCHAplica patch em um Oracle Grid ou Oracle Database (move gihome / move database)

O tipo de documento utilizado para enviar o corpo da requisição e receber o resultado é JSON. Toda operação que não seja do tipo GET, na prática resulta em um JOB do FPP que é agendado para executar em background, permitindo que a resposta da API sempre fique na casa de milisegundos, independente da operação.

Cada requisição retorna o número do JOB na resposta, assim como uma URL para consultar o status do JOB via requisição GET. A partir desse ponto a aplicação terceira precisa consultar essa URL regularmente para monitorar o seu status, até ser concluído com status de FAILED ou SUCCEEDED.

Por baixo do capô, a API interpreta o conteúdo do JSON enviado na requisição, valida e converte em um comando “rhpctl”. O resultado disso é que no final no dia tudo que fazemos via API ou linha de comando caminham juntos, não havendo problemas de conflito ao usar as duas abordagens de forma intercambiada. Por exemplo, não há problema em criar uma workingcopy via linha de comando e realizar o move via API, ou vice versa.

1) Configuração Inicial no FPP Server

A configuração do lado do FPP Server é muito simples considerando uma instalação padrão, sendo necessário exportar o certificado do FPP Server e criar um usuário de API com as permissões necessárias. Tudo é gerenciado pelo próprio serviço do FPP e os comandos utilizados não fogem muito daqueles que já estamos acostumados.

Exportando o Certificado para Comunicação com HTTPS

Assume-se que a sessão atual está configurada com as variáveis de ambiente do Grid Infrastructure.

Como pré requisito, a opção “HTTP Secure” deve estar configurada com valor “enabled” no recurso rhpserver (esse o default):

srvctl config rhpserver | grep HTTP

Verifique que o Grid tem um certificado padrão da Oracle com status ENABLED:

crskeytoolctl -listcertificates

Obtém o certificado público no formato PEM. O comando abaixo gera um arquivo no diretório local com o padrão <Cluster ID.pem>:

crskeytoolctl -printrootcert

Após gerar o arquivo com nome padrão (não dá pra customizar na saída), renomeie com um nome mais amigável. Exemplo:

mv /home/grid/81b4d09c2d855fc9bfeca3d4b193ebaf.pem fpp_public_cert.pem

Criando Usuário da API

Para realizar qualquer operação no FPP usando REST API, além do certificado para usar o protocolo HTTPS, é necessário um usuário e senha específico para autenticação.

O FPP tem um sistema próprio de usuários e permissões através de Roles, e cada usuário do FPP é vinculado a um usuário do SO onde ele está instalado. Neste contexto, o usuário do FPP é chamado de “FPP User”, e o usuário do SO é chamado de CRS User (o usuário do SO que tem privilégio para executar comandos no CRS, como crsctl, rhpctl, etc).

No exemplo abaixo, estou criando um usuário no FPP com nome “dibiei_rest” e a flag -restuser, que indica que este usuário pode interagir com o FPP via REST API. Neste exemplo estamos vinculado ao usuário de SO “grid”, que é o owner de instalação do FPP Server e tem permissão Full para realizar qualquer operação.

rhpctl register user -user dibiei_rest -restuser -email maicon@example.com -rhpuser grid

Após executar este comando, será solicitado uma senha para o novo usuário, e é esta senha que será usada pela aplicação que realizar alguma chamada no endpoint do FPP. Note que se trata da criação de uma senha nova e não precisa ser igual a senha do usuário do SO.

Para entendimento das próximas etapas, neste exemplo, usei a super senha “dibiei123”.

Atenção: Ele não solicita a verificação da senha em duas etapas, o que você digitar aqui, será aceito como a senha “desejada”.

É possível criar usuários adicionais no servidor do FPP, vincular ao grupo de SO que permite execução de comandos do Grid, e atribuir permissões mais restritivas para este novo usuário usando o comando “rhpctl grant role -user <username> -role <FPP Role name>

2) Teste com CURL

Exporte a variável de ambiente CURL_CA_BUNDLE apontando para o caminho do certificado obtido anteriormente:

export CURL_CA_BUNDLE=/home/grid/fpp_public_cert.pem

Modelo básico dos Endpoints da API do FPP, onde FPP Server representa o hostname/VIP do FPP, e PATH representa o complemento específico de cada função oferecida pela API, conforme documentado em All REST Endpoints:

 https://<FPP Server>:8894/rhp-restapi/rhp/<PATH>

Teste uma operação GET para listar as GoldImage existentes no FPP, note que para este exemplo, o “PATH” é “images”:

curl -u dibiei_rest -X GET "https://fppserver:8894/rhp-restapi/rhp/images"

Este comando irá solicitar a senha do usuário dibiei_rest e retornará a lista de GoldImage no formato de JSON:

[grid@fppserver ~]$ curl -u dibiei_rest -X GET "https://fppserver:8894/rhp-restapi/rhp/images"
Enter host password for user 'dibiei_rest':
{"items":[{"links":[{"uri":"https://fppserver:8894/rhp-restapi/rhp/images/DB1919","rel":"self"}],"imageId":"DB1919"},{"links":[{"uri":"https://fppserver:8894/rhp-restapi/rhp/images/DB1921","rel":"self"}],"imageId":"DB1921"},{"links":[{"uri":"https://fppserver:8894/rhp-restapi/rhp/images/DB1922","rel":"self"}],"imageId":"DB1922"},{"links":[{"uri":"https://fppserver:8894/rhp-restapi/rhp/images/GI1919","rel":"self"}],"imageId":"GI1919"},{"links":[{"uri":"https://fppserver:8894/rhp-restapi/rhp/images/GI1921","rel":"self"}],"imageId":"GI1921"}]}

Opcionalmente, para obter o resultado com o JSON com um formato mais legível, podemos usar o utilitário “jq”.

O utilitário jq não é padrão no Oracle Linux , mas pode ser instalado facilmente com o comando “yum install jq”.

[grid@fppserver ~]$ curl -s -u dibiei_rest -X GET "https://fppserver:8894/rhp-restapi/rhp/images" | jq
Enter host password for user 'dibiei_rest':
{
  "items": [
    {
      "links": [
        {
          "uri": "https://fppserver:8894/rhp-restapi/rhp/images/DB1919",
          "rel": "self"
        }
      ],
      "imageId": "DB1919"
    },
    {
      "links": [
        {
          "uri": "https://fppserver:8894/rhp-restapi/rhp/images/DB1921",
          "rel": "self"
        }
      ],
      "imageId": "DB1921"
    },
    {
      "links": [
        {
          "uri": "https://fppserver:8894/rhp-restapi/rhp/images/DB1922",
          "rel": "self"
        }
      ],
      "imageId": "DB1922"
    },
    {
      "links": [
        {
          "uri": "https://fppserver:8894/rhp-restapi/rhp/images/GI1919",
          "rel": "self"
        }
      ],
      "imageId": "GI1919"
    },
    {
      "links": [
        {
          "uri": "https://fppserver:8894/rhp-restapi/rhp/images/GI1921",
          "rel": "self"
        }
      ],
      "imageId": "GI1921"
    }
  ]
}

O valor apresentado no atributo “uri” de cada GoldImage, indica o endpoint que retorna a informação detalhada de cada GoldImage.

Exemplo, para obter informações da GoldImage DB1921, eu uso a URL retornada no JSON do comando anterior. Note que agora o PATH é “images/<Image Name>”:

https://<FPP Server>:8894/rhp-restapi/rhp/images/<Gold Image>
[grid@fppserver ~]$ curl -s -u dibiei_rest -X GET "https://fppserver:8894/rhp-restapi/rhp/images/DB1921" | jq
Enter host password for user 'dibiei_rest':
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/images/DB1921",
      "rel": "self"
    }
  ],
  "imageId": "DB1921",
  "clientName": "fppserver",
  "complete": true,
  "parentImage": "",
  "platform": "Linux_AMD64",
  "containsNonRollingPatch": false,
  "groupsConfigured": "OSDBA=oinstall,OSOPER=oinstall,OSBACKUP=oinstall,OSDG=oinstall,OSKM=oinstall,OSRAC=oinstall",
  "roles": [
    "USER:grid@fppserver",
    "ROLE:OTHER",
    "ROLE:GH_IMG_PUBLISH",
    "ROLE:GH_IMG_ADMIN",
    "ROLE:GH_IMG_VISIBILITY"
  ],
  "version": "19.0.0.0.0:19.21.0.0.0",
  "imageState": "PUBLISHED",
  "imageSize": 10360,
  "patches": [
    "35648110",
    "35638318",
    "35655527",
    "35643107"
  ],
  "homePath": "/fpp_images/images/iDB1921106292/.ACFS/snaps/iDB1921/swhome",
  "imageType": "ORACLEDBSOFTWARE",
  "owner": "grid@fppserver"
}

3) Criando uma WorkingCopy

A partir daqui, para cada operação que não seja do tipo GET, normalmente precisaremos especficiar um “Body” da requisição no formato de documento JSON. Para facilitar, podemos utilzar um arquivo contendo este JSON e referenciá-lo na chamada do comando CURL.

O conteúdo deste JSON basicamente são os atributos e valores que passariamos no comando “rhpctl” se estivessemos trabalhando via linha de comando, como o nome da credencial, o targetNode e etc.

Para os próximos exemplos, eu criei uma variável de ambiente USER_REST_PWD com a senha do usuário dibiei_rest, apenas para demonstrar a forma de executar o CURL informando usuário e senha.

[grid@fppserver ~]$ source user_rest.env
[grid@fppserver ~]$ echo $API_USER
dibiei_rest:dibiei123

A1) Primeiro criamos um arquivo .json com as informações da nova WorkingCopy.

Este é o conteúdo do arquivo “eval_WC_GI1921_lab02.json”:

[grid@fppserver ~]$ cat eval_WC_GI1921_lab02.json
{
    "path" : "/u01/app/product/19.0.0.0/GI1921",
    "oracleBase" : "/u01/app/grid",
    "storagetype" : "LOCAL",
    "imageName" : "GI1921",
    "workingcopy" : "WC_GI1921_lab02",
    "softwareOnly": true,
    "targetNode" : "lab02",
    "cred" : "root_dibiei_cred",
    "eval" : true
}

A2) Executando a operação de avaliação.

Exemplo do formato do comando, agora mudando o tipo de requisição para “POST” (-X), também é necessário especificar o tipo de conteúdo sendo transmitido (-H), assim como o conteúdo em si, que representa o “request body” (-d).

curl -s -u <user> -X POST -H "Content-Type: application/json" -d "@<File.json>" "<Endpoint URL>"
[grid@fppserver ~]$ curl -s -u $API_USER -X POST -H "Content-Type: application/json" -d "@eval_WC_GI1921_lab02.json" "https://fppserver:8894/rhp-restapi/rhp/workingcopies" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/47",
      "rel": "self"
    }
  ],
  "jobId": "47",
  "output": {}
}

Se for aceito com sucesso, a API cria um JOB no FPP e retorna um JSON informando o número do JOB, assim como a URL para consultar o status via requisição GET.

A3) Consultando o status da operação de avaliação (JOB 47):

[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/47" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/47",
      "rel": "self"
    }
  ],
  "jobId": "47",
  "status": "SUCCEEDED",
  "operation": "addWorkingCopy{cred=root_dibiei_cred, image=GI1921, softwareonly=, storagetype=LOCAL, schedule=2024-01-25T17:49:43Z, path=/u01/app/product/19.0.0.0/GI1921, eval=, root=TRUE, oraclebase=/u01/app/grid, workingcopy=WC_GI1921_lab02, user=grid, targetnode=lab02}",
  "output": {
    "links": [
      {
        "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/47/output?offset=0&limit=0",
        "rel": "self"
      }
    ]
  }
}

A4) Para executar a criação da WorkingCopy efetivamente, o comando abaixo foi trocado para ler o arquivo “add_WC_GI1921_lab02.json” ao invés do “eval_WC_GI1921_lab02.json”.

A única diferença no contéudo desses 2 arquivos é o atributo “eval” que teve o valor trocado de “true” para “false”.

[grid@fppserver ~]$ curl -s -u $API_USER -X POST -H "Content-Type: application/json" -d "@add_WC_GI1921_lab02.json" "https://fppserver:8894/rhp-restapi/rhp/workingcopies" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/50",
      "rel": "self"
    }
  ],
  "jobId": "50",
  "output": {}
}

Executando uma requisição GET na URL fornecida acima para consultar o status do JOB 50.

Note que o status atual é EXECUTING:

[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/50" | jq                                                                 {
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/50",
      "rel": "self"
    }
  ],
  "jobId": "50",
  "status": "EXECUTING",
  "operation": "addWorkingCopy{cred=root_dibiei_cred, image=GI1921, schedule=2024-01-25T19:07:44Z, path=/u01/app/product/19.0.0.0/GI1921, softwareonly=, root=TRUE, oraclebase=/u01/app/grid, workingcopy=WC_GI1921_lab02, user=grid, storagetype=LOCAL, targetnode=lab02}",
  "output": {
    "links": [
      {
        "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/50/output?offset=0&limit=0",
        "rel": "self"
      }
    ]
  }
}

Algum tempo depois, uma nova requisição retornando com o status SUCCEEDED:

[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/50" | jq                                                                 {
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/50",
      "rel": "self"
    }
  ],
  "jobId": "50",
  "status": "SUCCEEDED",
  "operation": "addWorkingCopy{cred=root_dibiei_cred, image=GI1921, schedule=2024-01-25T19:07:44Z, path=/u01/app/product/19.0.0.0/GI1921, softwareonly=, root=TRUE, oraclebase=/u01/app/grid, workingcopy=WC_GI1921_lab02, user=grid, storagetype=LOCAL, targetnode=lab02}",
  "output": {
    "links": [
      {
        "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/50/output?offset=0&limit=0",
        "rel": "self"
      }
    ]
  }
}

A URL retornada no atributo “links” do status do JOB pode ser usada para consultar o LOG da operação, que retorna o output equivalente ao do comando “rhpctl”.

Note que para consultar o log detalhado, eu uso uma opção adicional “-r ‘.output‘” para apresentar o resultado em um formado legível com quebra de linha onde originalmente o JSON é retornando com ESCAPE “\n”.

[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/50/output?offset=0&limit=0" | jq -r '.output'
fppserver.dibiei.com: Audit ID: 663
fppserver.dibiei.com: Creating snapshot "tmpGI1921WC_GI1921_lab02" ...
fppserver.dibiei.com: Changing the home ownership to user grid...
fppserver.dibiei.com: Copying software contents to Local File System ...
fppserver.dibiei.com: Starting clone operation...
fppserver.dibiei.com: Using inventory file /etc/oraInst.loc to clone ...
lab02: Launching Oracle Grid Infrastructure Setup Wizard...
lab02:
lab02: [WARNING] [INS-13014] Target environment does not meet some optional requirements.
lab02:    CAUSE: Some of the optional prerequisites are not met. See logs for details. /u01/app/oraInventory/logs/GridSetupActions2024-01-25_04-32-37PM/gridSetupActions2024-01-25_04-32-37PM.log
lab02:    ACTION: Identify the list of failed prerequisite checks from the log: /u01/app/oraInventory/logs/GridSetupActions2024-01-25_04-32-37PM/gridSetupActions2024-01-25_04-32-37PM.log. Then either from the log file or from installation manual find the appropriate configuration to meet the prerequisites and fix it manually.
lab02: The response file for this session can be found at:
lab02:  /u01/app/product/19.0.0.0/GI1921/install/response/grid_2024-01-25_04-32-37PM.rsp
lab02:
lab02: You can find the log of this install session at:
lab02:  /u01/app/oraInventory/logs/GridSetupActions2024-01-25_04-32-37PM/gridSetupActions2024-01-25_04-32-37PM.log
lab02:
lab02: As a root user, execute the following script(s):
lab02:  1. /u01/app/product/19.0.0.0/GI1921/root.sh
lab02:
lab02: Execute /u01/app/product/19.0.0.0/GI1921/root.sh on the following nodes:
lab02: [lab02]
lab02:
lab02:
lab02: Successfully Setup Software with warning(s).
fppserver.dibiei.com: Successfully executed clone operation.
fppserver.dibiei.com: Executing root script on nodes [lab02].
lab02: Check /u01/app/product/19.0.0.0/GI1921/install/root_lab02_2024-01-25_16-34-03-703109408.log for the output of root script
fppserver.dibiei.com: Successfully executed root script on nodes [lab02].
fppserver.dibiei.com: Oracle home provisioned.
fppserver.dibiei.com: Working copy creation completed.

Dica: O mesmo JOB pode consultado via linha de comando no FPP Server:
rhpctl query job -jobid 50

Para provisionar a WorkingCopy de um DB Home, a abordagem é a mesma, precisando apenas trocar o arquivo com um JSON contendo os atributos específicos de um Oracle Home.

Os próximos exemplos são execuções diretas sem usar a opção de avaliação, mas todos eles suportam este método se colocarmos o atributo “eval” com valor “true” no JSON.

Conteúdo do arquivo “add_WC_DB1921_lab02.json” usado como Body da requisição:

[grid@fppserver ~]$ cat add_WC_DB1921_lab02.json
{
    "path" : "/u01/app/oracle/product/19.0.0.0/DB1921",
    "oracleBase" : "/u01/app/oracle",
    "storagetype" : "LOCAL",
    "imageName" : "DB1921",
    "workingcopy" : "WC_DB1921_lab02",
    "user" : "oracle",
    "groups": "OSDBA=dba,OSOPER=dba,OSDG=dba,OSKM=dba,OSRAC=dba,OSBACKUP=dba",
    "targetNode" : "lab02",
    "cred" : "root_dibiei_cred",
    "eval" : false
}

Executando uma requisição POST com JSON Body mostrado acima::

[grid@fppserver ~]$ curl -s -u $API_USER -X POST -H "Content-Type: application/json" -d "@add_WC_DB1921_lab02.json" "https://fppserver:8894/rhp-restapi/rhp/workingcopies" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/51",
      "rel": "self"
    }
  ],
  "jobId": "51",
  "output": {}
}

Alguns minutos depois, consultando o status do JOB 51 com o status SUCCEEDED:

[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/51" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/51",
      "rel": "self"
    }
  ],
  "jobId": "51",
  "status": "SUCCEEDED",
  "operation": "addWorkingCopy{cred=root_dibiei_cred, image=DB1921, schedule=2024-01-25T20:33:48Z, path=/u01/app/oracle/product/19.0.0.0/DB1921, root=TRUE, groups=OSDBA=dba,OSOPER=dba,OSDG=dba,OSKM=dba,OSRAC=dba,OSBACKUP=dba, oraclebase=/u01/app/oracle, user=oracle, workingcopy=WC_DB1921_lab02, storagetype=LOCAL, targetnode=lab02}",
  "output": {
    "links": [
      {
        "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/51/output?offset=0&limit=0",
        "rel": "self"
      }
    ]
  }
}

4) Move do Grid Home e DB Home

Até o momento deste post eu não consegui realizar um move de GI Home com DB Home em uma única operação usando REST API. Na verdade, pelos testes que realizei, o problema parece estar relacionado com a opção “-json” do comando “rhpctl move gihome”, onde toda vez que tento realizar esse tipo de ação com os parâmetros “-auto” e “-dbhomes”, ele falha com um erro similar a este:

PRGO-1774 : The evaluation revealed potential failure for command "move gihome".
PRGR-118 : Working copy "null,"clusterMode"" does not exist.

Tendo essa restrição com solução ainda desconhecida pra mim até o momento, especificamente para o uso com REST API, tenho usado a abordagem de Move em duas etapas: Primeiro o GI Home, depois o DB Home.

Apesar de funcionalmente chegar no mesmo resultado, esse método com Move em 2 etapas requer 2 restart no banco de dados.

4.1) Move GRID

Para realizar uma operação de move GI Home, executamos uma requisição do tipo PATCH no endpoint da WorkingCopy do Grid criada em uma etapa anterior.

URL Template:

https://<FPP Server>:8894/rhp-restapi/rhp/workingcopies/<Source GI WorkingCopy>/gihome/<Target GI WorkingCopy>

Conteúdo do arquivo move_GI1921_lab02.json usado como Body da requisição PATCH:

[grid@fppserver ~]$ cat move_GI1921_lab02.json
{
    "targetNode" : "lab02",
    "cred" : "root_dibiei_cred",
    "eval" : "false"
}

4.1.1) Executando a requisição PATCH movendo o Grid da WorkingCopy WC_GI1919_lab02 para WC_GI1921_lab02:

[grid@fppserver ~]$ curl -s -u $API_USER -X PATCH -H "Content-Type: application/json" -d "@move_GI1921_lab02.json" "https://fppserver:8894/rhp-restapi/rhp/workingcopies/WC_GI1919_lab02/gihome/WC_GI1921_lab02" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/68",
      "rel": "self"
    }
  ],
  "jobId": "68",
  "output": {}
}

4.1.2) Consultando o status da operação:

############ running now
[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/68" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/68",
      "rel": "self"
    }
  ],
  "jobId": "68",
  "status": "EXECUTING",
  "operation": "moveGIHome{cred=root_dibiei_cred, sourcewc=WC_GI1919_lab02, schedule=2024-01-27T02:03:16Z, destwc=WC_GI1921_lab02, root=TRUE, user=grid, targetnode=lab02}",
  "output": {
    "links": [
      {
        "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/68/output?offset=0&limit=0",
        "rel": "self"
      }
    ]
  }
}


############ completed
[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/68" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/68",
      "rel": "self"
    }
  ],
  "jobId": "68",
  "status": "SUCCEEDED",
  "operation": "moveGIHome{cred=root_dibiei_cred, sourcewc=WC_GI1919_lab02, schedule=2024-01-27T02:03:16Z, destwc=WC_GI1921_lab02, root=TRUE, user=grid, targetnode=lab02}",
  "output": {
    "links": [
      {
        "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/68/output?offset=0&limit=0",
        "rel": "self"
      }
    ]
  }
}

4.2) Move DB Home

Para o DB Home, o nome da WorkingCopy de origem é especificado no próprio Endpoint, mas diferente do Grid, o nome da workingCopy de destino é especificado no JSON usado como Body da requisição PATCH.

Template da URL:

https://<FPP Server>:8894/rhp-restapi/rhp/workingcopies/<Source WorkingCopy>/databases

Conteúdo do arquivo “move_WC_DB1921_lab02.json”:

[grid@fppserver ~]$ cat move_WC_DB1921_lab02.json
{
   "patchedwc" : "WC_DB1921_lab02",
   "targetNode" : "lab02",
   "cred" : "root_dibiei_cred",
   "eval" : "false"
}

4.2.1) Executando a operação POST para Move do DB Home:

[grid@fppserver ~]$ curl -s -u $API_USER -X PATCH -H "Content-Type: application/json" -d "@move_WC_DB1921_lab02.json" "https://fppserver:8894/rhp-restapi/rhp/workingcopies/WC_DB1919_lab02/databases" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/76",
      "rel": "self"
    }
  ],
  "jobId": "76",
  "output": {}
}

4.2.2) Consultando o status do JOB 76: SUCCEEDED

[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/76" | jq
{
  "links": [
    {
      "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/76",
      "rel": "self"
    }
  ],
  "jobId": "76",
  "status": "SUCCEEDED",
  "operation": "moveDatabase{cred=root_dibiei_cred, sourcewc=WC_DB1919_lab02, schedule=2024-01-27T22:33:49Z, root=TRUE, patchedwc=WC_DB1921_lab02, user=grid, targetnode=lab02}",
  "output": {
    "links": [
      {
        "uri": "https://fppserver:8894/rhp-restapi/rhp/jobs/76/output?offset=0&limit=0",
        "rel": "self"
      }
    ]
  }
}

4.2.3) Consultando o detalhamento do Output, podemos ver que o Move já foi concluído e o datapatch foi executado com sucesso nos bancos “cdbsoe” e “cdb19c”:

[grid@fppserver ~]$ curl -s -u $API_USER -X GET "https://fppserver:8894/rhp-restapi/rhp/jobs/76/output" | jq -r '.output'
fppserver.dibiei.com: Audit ID: 858
fppserver.dibiei.com: verifying versions of Oracle homes ...
fppserver.dibiei.com: verifying owners of Oracle homes ...
fppserver.dibiei.com: verifying groups of Oracle homes ...
fppserver.dibiei.com: retrieving information about databases being moved ...
fppserver.dibiei.com: starting to move the following databases: "cdb19c,cdbsoe"
fppserver.dibiei.com: moving databases: "cdb19c,cdbsoe" on nodes: "lab02"
fppserver.dibiei.com: retrieving status of databases "cdb19c,cdbsoe"...
fppserver.dibiei.com: copying database configuration files from Oracle home "/u01/app/oracle/product/19.0.0.0/DB1919" to Oracle home "/u01/app/oracle/product/19.0.0.0/DB1921" ...
fppserver.dibiei.com: stopping services of databases "cdbsoe,cdb19c" ...
fppserver.dibiei.com: Processing arguments file /u01/app/grid/crsdata/fppserver/rhp/conf/rhp.pref
fppserver.dibiei.com: Processing arguments file /u01/app/grid/crsdata/fppserver/rhp/conf/rhp.pref
fppserver.dibiei.com: Executing datapatch for DB 'cdbsoe' ...
fppserver.dibiei.com: Executing datapatch for DB 'cdb19c' ...
fppserver.dibiei.com: Processing arguments file /u01/app/grid/crsdata/fppserver/rhp/conf/rhp.pref
fppserver.dibiei.com: Processing arguments file /u01/app/grid/crsdata/fppserver/rhp/conf/rhp.pref
lab02: database Type:
lab02: database Type:
lab02: executing start command /u01/app/oracle/product/19.0.0.0/DB1921/bin/srvctl start database -d cdb19c
lab02: executing start command /u01/app/oracle/product/19.0.0.0/DB1921/bin/srvctl start database -d cdbsoe
fppserver.dibiei.com: Datapatch executed succesfully for DB 'cdbsoe' ...
lab02: trying datapatch run for cdb19c, attempt### 1 ###
lab02: datapatch command /u01/app/oracle/product/19.0.0.0/DB1921/OPatch/datapatch  -db cdb19c datapatch completed successfully for database : cdb19c
fppserver.dibiei.com: Datapatch executed succesfully for DB 'cdb19c' ...
Databases moved from Oracle home "/u01/app/oracle/product/19.0.0.0/DB1919" to Oracle home "/u01/app/oracle/product/19.0.0.0/DB1921" : "cdbsoe,cdb19c"

5) Exemplo Com Postman

O Postman é uma ferramenta gratuíta para teste de API com uma interface gráfica e intuítiva, disponível para Windows, Mac e Linux.

Você pode fazer o download aqui.

Neste exemplo, estou usando o Postman em uma máquina Windows.

Primeiros passos

5.1) Clique no sinal de “+”

5.2) Preencha os campos abaixo com as informações da API do FPP Server, como o Endpoint e o usuário e senha (neste exemplo de teste a senha está sendo passada em texto aberto):

5.3) Clique em Settings, em na opção “Enable SSL certificate verification”, clique no link “settings” novamente:

5.4) Selecione o arquivo do certificado .pem na sua máquina (gerado FPP Server):

5.5) Agora podemos submeter a requisição clicando em “Send”.

Verifique o valor apresentado em “Status”, e em “Body”.

Observe que temos a mesma resposta com JSON demonstrada nos exemplos com CURL:

Clique com o botão direito sob a aba atual e clique em “Duplicate tab”:

Na nova aba, mude o tipo da requisição de GET para POST, mude a URL para o endpoint usado para criar WorkingCopy.

Clique em “Body”, selecione a opção “raw” e selecione o tipo JSON.

Informe um JSON com os parâmetros que desejar usar na nova WorkingCopy. Neste exemplo, estou usando o mesmo modelo de JSON usado no exemplo com CURL, mas informando um servidor de destino diferente, assim como outra GoldImage: DB1922.

Clique em “Send”:

Requisição aceita a e JOB 74 criado no FPP Server:

Agora na outra aba, podemos executar uma requisição GET na URL do JOB retornado acima:

Clicando em “Send” novamente para obter um status atualizado:

Mude o tipo de requisição para DELETE e informe o Endpoint da WorkingCopy que deseja deletar. Em Body, informe apenas a credencial de acesso ao targetNode vinculado a WorkingCopy:

Consultando o status da operação DELETE (executando GET na URL do JOB gerado acima):

Conclusão

Este post demonstrou como interagir com o Oracle Fleet Patching and Provisioning usando o recurso de REST API nativo desta solução, cobrindo desde a configuração inicial, assim como exemplos de operações básicas para aplicar patch no Grid e RDBMS realizando chamadas com o CURL. Ao final, foi demonstrado como utilizar o aplicativo Postman para testar as requisições através de uma interface gráfica e amigável, o que normalmente é mais produtivo no desenvolvimento de um projeto de integração usando este tipo de API.

REST API for Fleet Patching and Provisioning

One thought on “Usando o Oracle Fleet Patching and Provisioning (FPP) com REST API”

Leave a Reply to Como Controlar a Ordem e Adicionar Pausa Entre os Nodes do RAC Atualizados com Fleet Patching and Provisioning (FPP) – Blog do DibieiCancel reply

Discover more from Blog do Dibiei

Subscribe now to keep reading and get access to the full archive.

Continue reading