{"id":382,"date":"2021-02-26T02:42:15","date_gmt":"2021-02-26T02:42:15","guid":{"rendered":"https:\/\/adrianotanaka.com.br\/?p=382"},"modified":"2022-03-11T19:17:45","modified_gmt":"2022-03-11T19:17:45","slug":"oci-script-para-gerar-relatorio-de-backups","status":"publish","type":"post","link":"https:\/\/adrianotanaka.com.br\/index.php\/2021\/02\/26\/oci-script-para-gerar-relatorio-de-backups\/","title":{"rendered":"OCI &#8211; Script para gerar relat\u00f3rio de backups"},"content":{"rendered":"\n<p>Decidi criar esse script para auxiliar no monitoramento dos backups dos discos do OCI, com ele fica bem simples fazer um agendamento por exemplo e receber todos os dias um relat\u00f3rio de como est\u00e3o seus backups, dessa forma voc\u00ea vai poder receber um alerta caso existam discos sem backup.<\/p>\n\n\n\n<p>Abaixo explico os peda\u00e7os do c\u00f3digo e no final disponibilizo o c\u00f3digo completo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Requisitos<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Servidor Linux no OCI dentro de um dynamic group para fazer as chamadas via cli<\/li><li>Utilit\u00e1rio mutt instalado e configurado no servidor para envio de e-mail<\/li><li>OCID do compartimento onde os discos est\u00e3o<\/li><li>&#8220;Nome&#8221; do AD onde os discos est\u00e3o<\/li><li>oci-cli instalado e configurado<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Fun\u00e7\u00f5es<\/h2>\n\n\n\n<p>Como j\u00e1 disse, o script \u00e9 bem simples, ele \u00e9 dividido basicamente entre listar os discos, fazer um loop no ocids buscando os backups e montar o e-mail.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Gerando os ocids<\/h2>\n\n\n\n<p>Essas duas fun\u00e7\u00f5es recebem como par\u00e2metros o AD e tamb\u00e9m o ocid do compartimento a ser analisado, a primeira busca o ocid e o display-name dos boot volumes enquanto que a segunda faz a mesma coisa para os block volumes:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">list_boot_vol() {\n    oci bv boot-volume list --availability-domain ${OCI_AD} -c ${OCI_COMPARTMENT} | jq -r '.data[] | [(.id+\",\"+.\"display-name\")] | @tsv' >boot-vol.txt\n}\n<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">list_block_vol() {\n    oci bv volume list -c ${OCI_COMPARTMENT} | jq -r '.data[] | [(.id+\",\"+.\"display-name\")] | @tsv' >block-vol.txt\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Verifica\u00e7\u00e3o de backups de boot volume<\/h2>\n\n\n\n<p>Nessa parte come\u00e7o a montar o e-mail(coloquei um pouco de CSS para n\u00e3o ficar t\u00e3o simples) e a parte importante \u00e9 esse loop que para cada ocid identificado, ele faz um requisi\u00e7\u00e3o buscando seus backups.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">while IFS=',' read -r disk_id disk_name; do\n        list_disk=$(oci bv boot-volume-backup list -c ${OCI_COMPARTMENT} --boot-volume-id ${disk_id} |\n            jq -r '.data[] | [(\"&lt;tr>&lt;td class=\\\"tg-0pky\\\">\"+.\"display-name\"+\"&lt;\/td>&lt;td class=\\\"tg-0pky\\\">\"+.\"time-created\"+\"&lt;\/td>&lt;td class=\\\"tg-0pky\\\">\"+.\"expiration-time\"+\"&lt;\/td>&lt;td class=\\\"tg-0pky\\\">\"+.\"lifecycle-state\"+\"&lt;\/td>&lt;\/tr>\")]|@tsv')\n        if [ $(echo -n \"$list_disk\" | wc -l) != 0 ]; then\n            echo \"&lt;div class=\\\"card\\\">&lt;div class=\\\"card-body\\\">&lt;div class=\\\"alert alert-success\\\" role=\\\"alert\\\">&lt;p>&lt;b>Disco:&lt;\/b> $disk_name &lt;br>&lt;b>OCID:&lt;\/b> $disk_id &lt;br>&lt;b>Quantidade de backups:&lt;\/b> $(echo \"$list_disk\" | wc -l)&lt;\/p>&lt;\/div>\" >>mail.html\n            echo \"&lt;table class=\\\"tg\\\">\n            &lt;tr>\n              &lt;th class=\\\"tg-0pky\\\">Backup&lt;\/th>\n              &lt;th class=\\\"tg-0pky\\\">Criado em&lt;\/th>\n              &lt;th class=\\\"tg-0pky\\\">Expira em&lt;\/th>\n              &lt;th class=\\\"tg-0pky\\\">Status&lt;\/th>\n            &lt;\/tr>\n          &lt;\/thead>\n        &lt;tbody>$list_disk&lt;\/tbody>\n        &lt;\/table>&lt;\/div>&lt;\/div>\" >>mail.html\n        else\n            echo \"&lt;div class=\\\"card\\\">&lt;div class=\\\"card-body\\\">&lt;p class=\\\"alert alert-danger\\\" role=\\\"alert\\\"> &lt;b>Disco:&lt;\/b> $disk_name &lt;br>&lt;b style=\\\"color:red;\\\">OCID:&lt;\/b> $disk_id &lt;br>&lt;b style=\\\"color:red;\\\">Quantidade de backups:&lt;\/b> $(echo -n \"$list_disk\" | wc -l)&lt;\/p>&lt;\/div>&lt;\/div>&lt;br>\" >>mail.html\n        fi\ndone &lt;boot-vol.txt<\/pre>\n\n\n\n<p>Baseado no arquivo boot-vol que geramos no passo anterior, um loop \u00e9 executado verificando se existe ou n\u00e3o o backup, caso existam backups, o texto recebe um fundo verde e uma tabela \u00e9 gerada com os backups registrados, caso n\u00e3o seja encontrado nenhum backup o texto recebe um fundo vermelho:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"943\" height=\"293\" src=\"https:\/\/adrianotanaka.com.br\/wp-content\/uploads\/2021\/02\/image-22.png\" alt=\"\" class=\"wp-image-387\" srcset=\"https:\/\/adrianotanaka.com.br\/wp-content\/uploads\/2021\/02\/image-22.png 943w, https:\/\/adrianotanaka.com.br\/wp-content\/uploads\/2021\/02\/image-22-300x93.png 300w, https:\/\/adrianotanaka.com.br\/wp-content\/uploads\/2021\/02\/image-22-768x239.png 768w\" sizes=\"auto, (max-width: 943px) 100vw, 943px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"712\" height=\"102\" src=\"https:\/\/adrianotanaka.com.br\/wp-content\/uploads\/2021\/02\/image-21.png\" alt=\"\" class=\"wp-image-386\" srcset=\"https:\/\/adrianotanaka.com.br\/wp-content\/uploads\/2021\/02\/image-21.png 712w, https:\/\/adrianotanaka.com.br\/wp-content\/uploads\/2021\/02\/image-21-300x43.png 300w\" sizes=\"auto, (max-width: 712px) 100vw, 712px\" \/><\/figure>\n\n\n\n<p>Os backups realizados sob demanda aparecem sem data de expira\u00e7\u00e3o, isso tamb\u00e9m \u00e9 bom para caso voc\u00ea tenha esquecido algum backup fora da politica padr\u00e3o.<\/p>\n\n\n\n<p>Para ambas as op\u00e7\u00f5es, al\u00e9m do nome do disco tamb\u00e9m retorno o ocid para caso precise usar a barra de pesquisa do OCI para encontrar o disco e aplicar a politica de backup nele.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verifica\u00e7\u00e3o de backups de block volumes<\/h2>\n\n\n\n<p>A mesma ideia \u00e9 aplicada aos backups de block volumes que est\u00e3o no arquivo block-vol.txt e aqui encerramos o nosso e-mail:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> while IFS=',' read -r disk_id disk_name; do\n        list_disk=$(oci bv backup list -c ${OCI_COMPARTMENT} --volume-id ${disk_id} | jq -r '.data[] | [(\"&lt;tr>&lt;td>\"+.\"display-name\"+\"&lt;\/td>&lt;td>\"+.\"time-created\"+\"&lt;\/td>&lt;td>\"+.\"expiration-time\"+\"&lt;\/td>&lt;td>\"+.\"lifecycle-state\"+\"&lt;\/td>&lt;\/tr>\")]|@tsv')\n        if [ $(echo -n \"$list_disk\" | wc -l) != 0 ]; then\n            echo \"&lt;div class=\\\"card\\\">&lt;div class=\\\"card-body\\\">&lt;div class=\\\"alert alert-success\\\" role=\\\"alert\\\">&lt;p>&lt;b>Disco:&lt;\/b> $disk_name &lt;br>&lt;b>OCID:&lt;\/b> $disk_id &lt;br>&lt;b>Quantidade de backups:&lt;\/b> $(echo \"$list_disk\" | wc -l)&lt;\/p>&lt;\/div>&lt;br>\" >>mail.html\n            echo \"&lt;table class=\\\"tg\\\">\n                  &lt;tr>\n                    &lt;th class=\\\"tg-0pky\\\">Backup&lt;\/th>\n                    &lt;th class=\\\"tg-0pky\\\">Criado em&lt;\/th>\n                    &lt;th class=\\\"tg-0pky\\\">Expira em&lt;\/th>\n                    &lt;th class=\\\"tg-0pky\\\">Status&lt;\/th>\n                  &lt;\/tr>\n                &lt;\/thead>\n                &lt;tbody>$list_disk&lt;\/tbody>\n                &lt;\/table>&lt;\/div>&lt;\/div>\" >>mail.html\n        else\n            echo \"&lt;div class=\\\"card\\\">&lt;div class=\\\"card-body\\\">&lt;p class=\\\"alert alert-danger\\\" role=\\\"alert\\\"> &lt;b>Disco:&lt;\/b> $disk_name &lt;br>&lt;b>OCID:&lt;\/b> $disk_id &lt;br>&lt;b>Quantidade de backups:&lt;\/b> $(echo -n \"$list_disk\" | wc -l) &lt;\/p>&lt;\/div>&lt;\/div>&lt;br>\" >>mail.html\n        fi\n    done &lt;block-vol.txt\n    echo \"&lt;figure class=\\\"text-center\\\">&lt;p class=\\\"h6\\\">Lista de discos e seus backups no compartimento $COMPARTMENT_NAME gerado em $DATA $HORA&lt;\/p>&lt;\/figure>\" >>mail.html\n    echo \"&lt;\/body>&lt;\/html>\" >>mail.html<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Email<\/h2>\n\n\n\n<p>Todos os resultados s\u00e3o salvos em um arquivo chamado <strong>mail.htm<\/strong>l no diret\u00f3rio onde o script est\u00e1 sendo executado e ele vira o corpo do nosso e-mail:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">send_mail() {\n    cat mail.html | mutt -e \"set content_type=text\/html\" -e \" my_hdr From:bkp-report\" -s \"Backups do compartimento $COMPARTMENT_NAME $DATA\" $EMAIL\n}<\/pre>\n\n\n\n<p>Preferi fazer dessa forma(apesar de perdemos um pouco a formata\u00e7\u00e3o no corpo do e-mail) pois alguns provedores podem acabar bloqueando anexos do tipo html.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Executando<\/h2>\n\n\n\n<p>A execu\u00e7\u00e3o do script \u00e9 bem simples e para isso s\u00f3 precisamos passar o nome do AD onde os discos est\u00e3o, o ocid do compartimento, nome do compartimento e para qual e-mail deve ser enviado:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">.\/bkp-report.sh cEcK:SA-SAOPAULO-1-AD-1 ocid1.compartment.oc1..aXXXXXX COMPARTIMENTO_XYZ email@gmail.com<\/pre>\n\n\n\n<p>Voc\u00ea tamb\u00e9m pode fazer um agendamento no crontab para receber diariamente o relat\u00f3rio<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">30 03 * * * bkp-report.sh cEcK:SA-SAOPAULO-1-AD-1 ocid1.compartment.oc1..aXXXXXX COMPARTIMENTO_XYZ email@gmail.com<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Considera\u00e7\u00f5es<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Dependendo da quantidade de discos no ambiente, o script pode demorar muito para finalizar sua execu\u00e7\u00e3o, voc\u00ea pode acompanhar o status dando um tail no arquivo mail.html<\/li><li>Enviar html no corpo do e-mail n\u00e3o \u00e9 uma coisa t\u00e3o simples, nas minhas primeiras tentativas eu consegui criar um layout bem melhor mas ele n\u00e3o era respeitado, por isso alguns erros de posicionamento podem ocorrer<\/li><li>Estou ajustando uma vers\u00e3o que ao inv\u00e9s de gerar o arquivo html e enviar por e-mail, vai criar um arquivo csv que pode ser aberto no excel para facilitar por exemplo a cria\u00e7\u00e3o de gr\u00e1ficos ou algo do tipo<\/li><\/ul>\n\n\n\n<p>O c\u00f3digo completo pode ser encontrado no meu github -> <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/adrianotanaka\/scripts\/blob\/master\/oci\/cli\/bkp-report.sh\" target=\"_blank\">https:\/\/github.com\/adrianotanaka\/scripts\/blob\/master\/oci\/cli\/bkp-report.sh<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Decidi criar esse script para auxiliar no monitoramento dos backups dos discos do OCI, com ele fica bem simples fazer um agendamento por exemplo e receber todos os dias um relat\u00f3rio de como est\u00e3o seus backups, dessa forma voc\u00ea vai poder receber um alerta caso existam discos sem backup. Abaixo explico os peda\u00e7os do c\u00f3digo [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":389,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"material-hide-sections":[],"footnotes":""},"categories":[8,6,1],"tags":[],"class_list":["post-382","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oci","category-oracle","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/posts\/382","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/comments?post=382"}],"version-history":[{"count":11,"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/posts\/382\/revisions"}],"predecessor-version":[{"id":396,"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/posts\/382\/revisions\/396"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/media\/389"}],"wp:attachment":[{"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/media?parent=382"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/categories?post=382"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrianotanaka.com.br\/index.php\/wp-json\/wp\/v2\/tags?post=382"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}