diff --git a/fromDmOct2025/v930p2/check_list_alldb.sh b/fromDmOct2025/v930p2/check_list_alldb.sh new file mode 100644 index 0000000..b00a805 --- /dev/null +++ b/fromDmOct2025/v930p2/check_list_alldb.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Lists the registered DBs for a given Oracle Host or RAC +# and their assigned SLAs +# +# usage: oracle_list_db.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +#if [ $# -ne 1 ]; then +# echo "Usage: $0 " +# exit 1 +#fi + +#RBK_HOST=$1 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db" + +rest_api_get + +cat /tmp/rbkresponse.$$ | jq -r '.data[] | {id,name,isRelic,slaAssignment,retentionSlaDomainId,effectiveSlaDomainName,configuredSlaDomainName,isArchiveLogModeEnabled,dataGuardType,dataGuardGroupName,standaloneHostName,dbUniqueName,databaseRole,logBackupFrequencyInMinutes,lastSnapshotTim} ' | jq -r ' "\(.name), \(.id),\(.isRelic),\(.slaAssignment),\(.retentionSlaDomainId),\(.effectiveSlaDomainName),\(.configuredSlaDomainName),\(.isArchiveLogModeEnabled),\(.dataGuardType),\(.dataGuardGroupName),\(.standaloneHostName),\(.dbUniqueName),\(.databaseRole),\(.logBackupFrequencyInMinutes),\(.lastSnapshotTime)"' | awk -v FS="," 'BEGIN{print "Name id isRelic slaAssignment retentionSlaDomainId effectiveSlaDomainName configuredSlaDomainName ArcMode DG type DG group Hostname Db unique name DatabaseRole Logfreq Last Snapshot " ;print "============================================================================================================================================================================================================================================================================================================================="}{printf "%s %s\t %s\t %-15s %-38s %-28s %-28s %-8s %-17s %-19s %-30s %-15s %-18s %-10s %-10s %s %s",$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17 ORS}' + +cleanup diff --git a/fromDmOct2025/v930p2/check_list_alldb_new.sh b/fromDmOct2025/v930p2/check_list_alldb_new.sh new file mode 100644 index 0000000..54d4b2c --- /dev/null +++ b/fromDmOct2025/v930p2/check_list_alldb_new.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Lists the registered DBs for a given Oracle Host or RAC +# and their assigned SLAs +# +# usage: oracle_list_db.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +#if [ $# -ne 1 ]; then +# echo "Usage: $0 " +# exit 1 +#fi + +#RBK_HOST=$1 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db" + +rest_api_get + +cat /tmp/rbkresponse.$$ | jq -r '.data[] | {id,name,isRelic,slaAssignment,retentionSlaDomainId,effectiveSlaDomainName,configuredSlaDomainName,isArchiveLogModeEnabled,dataGuardType,dataGuardGroupName,standaloneHostName,dbUniqueName,databaseRole,logBackupFrequencyInMinutes,lastSnapshotTime,isDbLocalToTheCluster} ' | jq -r ' "\(.name), \(.id),\(.isRelic),\(.slaAssignment),\(.retentionSlaDomainId),\(.effectiveSlaDomainName),\(.configuredSlaDomainName),\(.isArchiveLogModeEnabled),\(.dataGuardType),\(.dataGuardGroupName),\(.standaloneHostName),\(.dbUniqueName),\(.databaseRole),\(.logBackupFrequencyInMinutes),\(.lastSnapshotTime),\(.isDbLocalToTheCluster)"' | awk -v FS="," 'BEGIN{print "Name id isRelic slaAssignment retentionSlaDomainId effectiveSlaDomainName configuredSlaDomainName ArcMode DG type DG group Hostname Db unique name DatabaseRole Logfreq Last Snapshot isDbLocalToTheCluster " ;print "==================================================================================================================================================================================================================================================================================================================================================================================================="}{printf "%s %s\t %s\t %-15s %-38s %-43s %-43s %-8s %-17s %-19s %-30s %-15s %-18s %-10s %-10s %s %s %s",$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18 ORS}' + +#echo "file: /tmp/rbkresponse.$$ " +cleanup diff --git a/fromDmOct2025/v930p2/check_recoverable_range.sh b/fromDmOct2025/v930p2/check_recoverable_range.sh new file mode 100644 index 0000000..243fd30 --- /dev/null +++ b/fromDmOct2025/v930p2/check_recoverable_range.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# +# Fetch recoverable ranges for a given Oracle DB +# v0.2 - James Pattinson - August 2021 +# v0.3 - Gerald Bailat - november 2024 - Add the option -R to see the recoverable range of the replicated backupfile +# +# usage: oracle_get_rr.sh [-h |local] + +SCRIPT=`basename $0` +echo "script ${SCRIPT}" + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h |local] " 1>&2; exit 1; } + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + RBK_HOST_TXT="${RBK_HOST}" + if [ "${RBK_HOST}" = "local" ] ; then + echo " The script will look for the “recoverable range” from the system where the script is executed" + RBK_HOST="" + fi + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage + exit 1 +fi +if [ `ps -ef | grep ora_pmon_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + #echo "Sid: $db is down, `hostname -s` " + ROLE="unknown" + STATUS=down +else + #echo "Sid: $db is up, `hostname -s` " + if [ `ps -ef | grep ora_arc[0-9]_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + STATUS="no-/mnt" + else + STATUS=up + fi + if [ `ps -ef | grep ora_mrp[0-9]_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + #echo "Sid: $db is stby, `hostname -s` " + ROLE=prim + else + #echo "Sid: $db is prim, `hostname -s` " + ROLE=stby + fi +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +ret=0 +# API call to list Oracle DBs +find_database + +echo Fetching Recoverable Ranges for $RBK_SID on $RBK_HOST + +# API call to get the recoverable range +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/recoverable_range" +http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") + +# echo "ret $ret" +echo -e "SID\t Hostname Status Role Start Time\t\t\tEnd Time\t\t\tStatus" +echo -e "-------- -------- ------- ------- ----------\t\t\t--------\t\t\t------" + + +if [ $ret -ne 0 ] ; then + RESULT_GET=" No_date No_date KO" + if [ ! -z "${INFO_RR_PROBLEM}" ] ; then + echo "${INFO_RR_PROBLEM}" + fi +else + RESULT_GET=`cat /tmp/rbkresponse.$$ | jq -r '.data[]' | jq -r ' "\(.beginTime)\t\(.endTime)\t\(.status)"'` + if [ -z "${RESULT_GET}" ] ; then + RESULT_GET=" No_date No_date KO" + if [ ! -z "${INFO_RR_PROBLEM}" ] ; then + echo "${INFO_RR_PROBLEM}" + fi + fi +fi + +echo "${RESULT_GET}" | sed "s/^/${RBK_SID} `hostname -s` ${STATUS} ${ROLE} /" | awk '{printf "%-10s %-13s %-7s %-7s %-30s %-31s %-12s\n" ,$1,$2,$3,$4,$5,$6,$7}' + +cleanup diff --git a/fromDmOct2025/v930p2/check_recoverable_range_debug.sh b/fromDmOct2025/v930p2/check_recoverable_range_debug.sh new file mode 100644 index 0000000..dc14f49 --- /dev/null +++ b/fromDmOct2025/v930p2/check_recoverable_range_debug.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# +# Fetch recoverable ranges for a given Oracle DB +# v0.2 - James Pattinson - August 2021 +# v0.3 - Gerald Bailat - november 2024 - Add the option -R to see the recoverable range of the replicated backupfile +# +# usage: oracle_get_rr.sh [-h |local] + +SCRIPT=`basename $0` +echo "script ${SCRIPT}" + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h |local] " 1>&2; exit 1; } + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + RBK_HOST_TXT="${RBK_HOST}" + if [ "${RBK_HOST}" = "local" ] ; then + echo " The script will look for the “recoverable range” from the system where the script is executed" + RBK_HOST="" + fi + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage + exit 1 +fi +if [ `ps -ef | grep ora_pmon_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + #echo "Sid: $db is down, `hostname -s` " + ROLE="unknown" + STATUS=down +else + #echo "Sid: $db is up, `hostname -s` " + if [ `ps -ef | grep ora_arc[0-9]_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + STATUS="no-/mnt" + else + STATUS=up + fi + if [ `ps -ef | grep ora_mrp[0-9]_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + #echo "Sid: $db is stby, `hostname -s` " + ROLE=prim + else + #echo "Sid: $db is prim, `hostname -s` " + ROLE=stby + fi +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +ret=0 +# API call to list Oracle DBs +find_database + +echo Fetching Recoverable Ranges for $RBK_SID on $RBK_HOST + +# API call to get the recoverable range +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/recoverable_range" +http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") + +# echo "ret $ret" +echo -e "SID\t Hostname Status Role Start Time\t\t\tEnd Time\t\t\tStatus" +echo -e "-------- -------- ------- ------- ----------\t\t\t--------\t\t\t------" + + +if [ $ret -ne 0 ] ; then + RESULT_GET=" No_date No_date KO" + if [ ! -z "${INFO_RR_PROBLEM}" ] ; then + echo "${INFO_RR_PROBLEM}" + fi +else + RESULT_GET=`cat /tmp/rbkresponse.$$ | jq -r '.data[]' | jq -r ' "\(.beginTime)\t\(.endTime)\t\(.status)"'` + if [ -z "${RESULT_GET}" ] ; then + RESULT_GET=" No_date No_date KO" + if [ ! -z "${INFO_RR_PROBLEM}" ] ; then + echo "${INFO_RR_PROBLEM}" + fi + fi +fi + +echo "${RESULT_GET}" | sed "s/^/${RBK_SID} `hostname -s` ${STATUS} ${ROLE} /" | awk '{printf "%-10s %-13s %-7s %-7s %-30s %-31s %-12s\n" ,$1,$2,$3,$4,$5,$6,$7}' + +# cleanup diff --git a/fromDmOct2025/v930p2/check_recoverable_range_debug2.sh b/fromDmOct2025/v930p2/check_recoverable_range_debug2.sh new file mode 100644 index 0000000..28cf18c --- /dev/null +++ b/fromDmOct2025/v930p2/check_recoverable_range_debug2.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# +# Fetch recoverable ranges for a given Oracle DB +# v0.2 - James Pattinson - August 2021 +# v0.3 - Gerald Bailat - november 2024 - Add the option -R to see the recoverable range of the replicated backupfile +# +# usage: oracle_get_rr.sh [-h |local] + +SCRIPT=`basename $0` +echo "script ${SCRIPT}" + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h |local] " 1>&2; exit 1; } + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + RBK_HOST_TXT="${RBK_HOST}" + if [ "${RBK_HOST}" = "local" ] ; then + echo " The script will look for the “recoverable range” from the system where the script is executed" + RBK_HOST="" + fi + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage + exit 1 +fi +if [ `ps -ef | grep ora_pmon_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + #echo "Sid: $db is down, `hostname -s` " + ROLE="unknown" + STATUS=down +else + #echo "Sid: $db is up, `hostname -s` " + if [ `ps -ef | grep ora_arc[0-9]_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + STATUS="no-/mnt" + else + STATUS=up + fi + if [ `ps -ef | grep ora_mrp[0-9]_$RBK_SID | grep -v " grep " | wc -l` -eq 0 ]; then + #echo "Sid: $db is stby, `hostname -s` " + ROLE=prim + else + #echo "Sid: $db is prim, `hostname -s` " + ROLE=stby + fi +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +ret=0 +# API call to list Oracle DBs +find_database + +echo Fetching Recoverable Ranges for $RBK_SID on $RBK_HOST + +# API call to get the recoverable range +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/recoverable_range" +http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") + +# echo "ret $ret" +echo -e "SID\t Hostname Status Role Start Time\t\t\tEnd Time\t\t\tStatus" +echo -e "-------- -------- ------- ------- ----------\t\t\t--------\t\t\t------" + + +if [ $ret -ne 0 ] ; then + echo "" >> /apprepos/oracle/orauti/shell/rubrik/rr_debug.log + echo "Date: `date "+%Y-%m-%d-%H.%M.%S"`, RC: $ret" >> /apprepos/oracle/orauti/shell/rubrik/rr_debug.log + RESULT_GET=" No_date No_date KO RC rbk $ret " >> /apprepos/oracle/orauti/shell/rubrik/rr_debug.log + if [ ! -z "${INFO_RR_PROBLEM}" ] ; then + echo "${INFO_RR_PROBLEM}" + fi +else + RESULT_GET=`cat /tmp/rbkresponse.$$ | jq -r '.data[]' | jq -r ' "\(.beginTime)\t\(.endTime)\t\(.status)"'` + echo "" >> /apprepos/oracle/orauti/shell/rubrik/rr_debug.log + # echo "Date: `date "+%Y-%m-%d-%H.%M.%S"`, RC: $ret" >> /apprepos/oracle/orauti/shell/rubrik/rr_debug.log + # echo "${RESULT_GET}" >> /apprepos/oracle/orauti/shell/rubrik/rr_debug.log + cat /tmp/rbkresponse.$$ | tee -a /apprepos/oracle/orauti/shell/rubrik/rr_debug.log + if [ -z "${RESULT_GET}" ] ; then + RESULT_GET=" No_date No_date KO " + # echo " Problem rr" | mail -s "Rubrik RR problem" gerald.bailat@mobi.ch + if [ ! -z "${INFO_RR_PROBLEM}" ] ; then + echo "${INFO_RR_PROBLEM}" + fi + fi +fi + +echo "${RESULT_GET}" | sed "s/^/${RBK_SID} `hostname -s` ${STATUS} ${ROLE} /" | awk '{printf "%-10s %-13s %-7s %-7s %-30s %-31s %-12s\n" ,$1,$2,$3,$4,$5,$6,$7}' + +# cleanup diff --git a/fromDmOct2025/v930p2/oracle_assign_sla.sh b/fromDmOct2025/v930p2/oracle_assign_sla.sh new file mode 100644 index 0000000..37cf6d5 --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_assign_sla.sh @@ -0,0 +1,138 @@ +#!/bin/bash +# +# v0.3 - James Pattinson - Feb 2025 +# +# usage: rsc_assign_sla.sh [-h ] [-c | -d] [sla name] +# +# If SLA name contains spaces then use quotes around it +# +# -c Clear any direct assignment +# -d Do Not Protect (Override any higher SLA assignment) + +MYDIR="$(dirname "$(realpath "$0")")" +#source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh +source $MYDIR/rsc_ops.sh + +usage() { echo "Usage: $0 [-h ] <-c | -d | sla name>" 1>&2; exit 1; } + +dg=0 + +SLA_OP="protectWithSlaId" +existingSnapshotRetention="NOT_APPLICABLE" + +while getopts "h:cd" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + c) + SLA_OP="noAssignment" + ;; + d) + SLA_OP="doNotProtect" + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 +RBK_SLA=$2 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +if [ "$SLA_OP" != 'protectWithSlaId' ]; then + new_sla_id=null + RBK_SLA=$SLA_OP + if [ "$SLA_OP" == 'doNotProtect' ]; then + existingSnapshotRetention="RETAIN_SNAPSHOTS" + fi +else + gql_SLAListQuery='query SLAListQuery($after: String, $first: Int, $filter: [GlobalSlaFilterInput!], $sortBy: SlaQuerySortByField, $sortOrder: SortOrder) { + slaDomains( + after: $after + first: $first + filter: $filter + sortBy: $sortBy + sortOrder: $sortOrder + ) { + edges { + node { + name + ... on GlobalSlaReply { + id + objectTypes + __typename + } + } + } + } +}' + + filter=$RBK_SLA + + variables="{ + \"shouldShowPausedClusters\":true, + \"filter\":[{\"field\":\"NAME\",\"text\":\"$filter\"},{\"field\":\"OBJECT_TYPE\",\"objectTypeList\":[\"ORACLE_OBJECT_TYPE\"]}], + \"sortBy\":\"NAME\", + \"sortOrder\":\"ASC\", + \"first\":50 + }" + + gqlQuery="$(echo $gql_SLAListQuery)" + gqlVars="$(echo $variables)" + rsc_gql_query + + #cat /tmp/rbkresponse.$$ + + new_sla_id=$(cat /tmp/rbkresponse.$$ | jq --arg SLA "$RBK_SLA" -r '.data.slaDomains.edges[] | select(.node.name == $SLA) | .node.id') + new_sla_id=\"${new_sla_id}\" +fi + +if [ -z $new_sla_id ]; then + echo FATAL: Unable to map SLA ID for $RBK_SLA + exit_with_error +else + echo "INFO: SLA ID for $RBK_SLA is $new_sla_id" +fi + +rsc_find_database +echo "INFO: DB found $rsc_db_id which is a $database_type instance" + +gql_AssignSlaMutation='mutation AssignSla($input: AssignSlaInput!) { + assignSla(input: $input) { + success + __typename + } +}' + +variables="{ + \"input\": { + \"objectIds\": [ + \"$rsc_db_id\" + ], + \"slaDomainAssignType\": \"$SLA_OP\", + \"slaOptionalId\": $new_sla_id, + \"existingSnapshotRetention\": \"$existingSnapshotRetention\", + \"shouldApplyToExistingSnapshots\": false, + \"shouldApplyToNonPolicySnapshots\": false + } + }" + +gqlQuery="$(echo $gql_AssignSlaMutation)" +gqlVars="$(echo $variables)" +rsc_gql_query + +cat /tmp/rbkresponse.$$ | jq -r + +echo Assigned $RBK_SLA to $RBK_SID + +cleanup + diff --git a/fromDmOct2025/v930p2/oracle_backup.sh b/fromDmOct2025/v930p2/oracle_backup.sh new file mode 100644 index 0000000..387814b --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_backup.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# +# Oracle Backup script for Die Mobiliar +# v0.3 - James Pattinson - October 2021 +# +# usage: oracle_backup.sh [-h ] [-a|-f|-n] +# +# -a archivelog backup +# -f force full backup +# -n do not wait for completion, submit job only +# +# The DB must already be protected by an SLA + +usage() { echo "Usage: $0 [-h ] [-a|-f|-n] " 1>&2; exit 1; } + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +archivelog=0 +full=0 + +while getopts "h:afn" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + a) + archivelog=1 + ;; + f) + full=1 + ;; + n) + nowait=1 + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +if [ $archivelog -eq 1 ] && [ $full -eq 1 ]; then + echo "FATAL: Can't specify both archivelog and full backup modes" + exit_with_error +fi + +echo Connecting to $RUBRIK_IP + +# API call to list Oracle DBs +find_database + +# API call to perform the snapshot +if [ $full -eq 1 ]; then + PAYLOAD="{\"slaId\":\"$sla_id\",\"forceFullSnapshot\":true}" + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/snapshot" + echo Requesting full backup for $RBK_SID on $RBK_HOST +elif [ $archivelog -eq 1 ]; then + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/log_backup" + PAYLOAD="{}" + echo Requesting log backup for $RBK_SID on $RBK_HOST +else + PAYLOAD="{\"slaId\":\"$sla_id\"}" + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/snapshot" + echo Requesting backup for $RBK_SID on $RBK_HOST +fi + +rest_api_post + +ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href') +check_status + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_delete_mount.sh b/fromDmOct2025/v930p2/oracle_delete_mount.sh new file mode 100644 index 0000000..8cbe02b --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_delete_mount.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Deletes an Oracle Live Mount +# +# usage: oracle_delete_mount.sh [-nf] +# +# -n do not wait for completion, submit job only +# -f force unmount + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +force=0 + +usage() { echo "Usage: $0 [-n][-f] " 1>&2; exit 1; } + +while getopts "nf" o; do + case "${o}" in + n) + nowait=1 + ;; + f) + force=true + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +if [ $# -ne 1 ]; then + usage +fi + +id=$1 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to remove Oracle Live Mount +if [ $force == "true" ]; then + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount/$id?force=true" +else + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount/$id" +fi + +echo Starting job to delete Live Mount with ID $id + +rest_api_delete + +# Check the status in a loop +ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href') +check_status + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_funcs.sh b/fromDmOct2025/v930p2/oracle_funcs.sh new file mode 100644 index 0000000..b4f0492 --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_funcs.sh @@ -0,0 +1,251 @@ +#!/bin/bash +# +#-------------------------------------------------------------------------------------------------------- +# Oracle shell script support functions +# v0.2 - James Pattinson - August 2021 +# v0.3 - U701053 - 30.03.2022 - if database not found, try to search with the ENDPOINT datagurad +# v0.4 - James Pattinson 25/01/23 - Adding support for Service Accounts +#-------------------------------------------------------------------------------------------------------- + +if [ -z "$OUTI" ]; then + OUTI=/apprepos/oracle/orauti +fi + +#MYDIR="$(dirname "$(realpath "$0")")" +#source $MYDIR/rbk_api.conf + +# -- Mobi config --------- +RBK_ENV=$OUTI/shell/rubrik/conf/rbk_env +# -- End Mobi config ---- + +# -- Mobi config ----------- +if [ -f "${RBK_ENV}" ] ; then + source ${RBK_ENV} +else + echo "The ${RBK_ENV} file is not found ...." + exit_with_error +fi +# -- End Mobi config ------- + +nowait=0 + +if [[ "$OSTYPE" == "darwin"* ]]; then + DATE=gdate +else + DATE=date +fi + +exit_with_error () { + rm -f /tmp/rbkresponse.$$ + echo Aborting Script! + exit 1 +} + +# for canceled status +exit_with_cancel () { + rm -f /tmp/rbkresponse.$$ + echo Canceling Script! + exit 1 +} + +# for undoing status +exit_with_undoing () { + rm -f /tmp/rbkresponse.$$ + echo undoing Script! + exit 1 +} + +check_http_error () { + # All good responses start with a 2 + if [ ${http_response:0:1} != "2" ]; then + echo FATAL: HTTP error from API call: $http_response. The server responded with: + cat /tmp/rbkresponse.$$ ; echo ; exit_with_error + fi +} + +# Given RBK_SID return $db_id of matching database +find_database () { + + # First get IDs of all the mounted DBs for this SID + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount" + rest_api_get + + cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.mountedDatabaseId!=null and .mountedDatabaseName==$SID) | .mountedDatabaseId' > /tmp/mountedDBs.$$ + + # Now get a list of Oracle DBs + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?name=$RBK_SID" + rest_api_get + + # If no dtaabse is found, try with dataguard + if [ `cat /tmp/rbkresponse.$$ | grep "id\":" | wc -l` -eq 0 ]; then + echo " DB not found, try with dataguard..." + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?is_data_guard_group=true&is_relic=false&name=$RBK_SID" + rest_api_get + fi + +#echo "=================================" +#cat /tmp/rbkresponse.$$ | jq -r '.data[]' | tee /tmp/titi +#echo "=================================" +#echo "cat /tmp/rbkresponse.$$ | jq -r '.data[]'" + + + # If no host is specified then just look for the DB with the right SID + if [ -z $RBK_HOST ]; then + + # get list of DB IDs in scope (sid matches and not a relic) + myDBs=$(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID and .isRelic==false) | .id' ; cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID and .isRelic==false) | .dataGuardGroupId' | sort | uniq) + + for db in $myDBs; do + id=$(echo $db | cut -d: -f 4) + if grep -q $id /tmp/mountedDBs.$$; then + continue + else + break + fi + done + + # Get the details for the specific DB ID + read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg ID "OracleDatabase:::$id" '.data[] | select(.id==$ID) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName')) + + # Host was specified + else + read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" --arg HOST "$RBK_HOST" '.data[] | select(.sid==$SID and .infraPath[0].name==$HOST and .isRelic==false) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName')) + fi + + if [ "$dg_type" == "DataGuardMember" ]; then + db_id=$dg_id + # Now find SLA of the DG GROUP not just the DB (which will be unprotected) + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id" + rest_api_get + sla_id=$(cat /tmp/rbkresponse.$$ | jq -r '.effectiveSlaDomainId') + fi + + if [ -z "$db_id" ]; then + echo FATAL: No DB found with SID $RBK_SID on host $RBK_HOST + if [ "${SCRIPT}" = "check_recoverable_range.sh" ] ; then + export ret=11 + else + exit_with_error + fi + else + echo " db_id is: $db_id" + fi +} + +check_get_token () { + + if [ -z "${AUTH_TOKEN}" ]; then + + if [[ "${ID}" =~ ^client ]]; then + # Looks like an RSC service account + id_string=$(echo $ID | cut -d\| -f 2) + else + # Not an RSC service account + id_string=$(echo $ID | cut -d: -f 4) + fi + + # If there is a cached credential file, use it + if [ -f ~/.rbksession.$id_string ]; then + read expiration token < <(echo $(cat ~/.rbksession.$id_string)) + # If token expires within 30 min, get a new one + if [ $($DATE +%s -d $expiration) -lt $(( $($DATE +%s) + 1800 )) ]; then + get_token + else + AUTH_TOKEN=$token + fi + else + get_token + fi + fi +} + +get_token () { + + MYENDPOINT="https://$RUBRIK_IP/api/v1/service_account/session" + MYPAYLOAD="{\"serviceAccountId\":\"$ID\",\"secret\":\"$SECRET\"}" + + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $MYENDPOINT -H "accept: application/json" -H "Content-Type: application/json" -d $MYPAYLOAD) + check_http_error + + AUTH_TOKEN=$(cat /tmp/rbkresponse.$$ | jq -r '.token') + SESSION=$(cat /tmp/rbkresponse.$$ | jq -r '.sessionId') + EXPIRATION=$(cat /tmp/rbkresponse.$$ | jq -r '.expirationTime') + echo "$EXPIRATION $AUTH_TOKEN" > ~/.rbksession.$id_string + +} + +# HTTP GET: Given $ENDPOINT write output to file +rest_api_get () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") + check_http_error +} + +# HTTP POST: Given $ENDPOINT and $PAYLOAD write output to file +rest_api_post () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD) + check_http_error +} + +rest_api_post_empty () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json") + check_http_error +} + +rest_api_patch () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X PATCH $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD) + check_http_error +} + +rest_api_delete () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X DELETE $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") + check_http_error +} + +get_cluster_uuid () { + ENDPOINT="https://$RUBRIK_IP/api/v1/cluster/me" + rest_api_get + cluster_uuid=$(cat /tmp/rbkresponse.$$ | jq -r .id) +} + +# Given an ENDPOINT of an async job, monitor it +check_status () { + if [ $nowait -ne 1 ]; then + # Check the status in a loop + while true; do + rest_api_get + status=$(cat /tmp/rbkresponse.$$ | jq -r '.status') + if [ $status != "SUCCEEDED" ] && [ $status != "FAILED" ] && [ $status != "CANCELED" ] && [ $status != "UNDOING" ]; then + echo Status is $status, checking in 30 seconds + else + if [ $status != "SUCCEEDED" ]; then + + if [ $status = "CANCELED" ] ; then + echo OPERATION FAILED WITH STATUS $status + exit_with_cancel + elif [ $status = "UNDOING" ] ; then + echo OPERATION FAILED WITH STATUS $status + exit_with_undoing + else + echo OPERATION FAILED WITH STATUS $status + exit_with_error + fi + else + echo OPERATION SUCCEEDED + exit 0 + fi + fi + sleep 30 + done + fi +} + +cleanup () { + rm -f /tmp/mountedDBs.$$ + rm -f /tmp/rbkresponse.$$ + rm -f /tmp/payload.$$ +} diff --git a/fromDmOct2025/v930p2/oracle_funcs_gbt.sh b/fromDmOct2025/v930p2/oracle_funcs_gbt.sh new file mode 100644 index 0000000..d62a53f --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_funcs_gbt.sh @@ -0,0 +1,251 @@ +#!/bin/bash +# +#-------------------------------------------------------------------------------------------------------- +# Oracle shell script support functions +# v0.2 - James Pattinson - August 2021 +# v0.3 - U701053 - 30.03.2022 - if database not found, try to search with the ENDPOINT datagurad +# v0.4 - James Pattinson 25/01/23 - Adding support for Service Accounts +#-------------------------------------------------------------------------------------------------------- + +if [ -z "$OUTI" ]; then + OUTI=/apprepos/oracle/orauti +fi + +MYDIR="$(dirname "$(realpath "$0")")" +#source $MYDIR/rbk_api.conf + +# -- Mobi config --------- +RBK_ENV=$OUTI/shell/rubrik/conf/rbk_env +# -- End Mobi config ---- + +# -- Mobi config ----------- +if [ -f "${RBK_ENV}" ] ; then + source ${RBK_ENV} +else + echo "The ${RBK_ENV} file is not found ...." + exit_with_error +fi +# -- End Mobi config ------- + +nowait=0 + +if [[ "$OSTYPE" == "darwin"* ]]; then + DATE=gdate +else + DATE=date +fi + +exit_with_error () { + rm -f /tmp/rbkresponse.$$ + echo Aborting Script! + exit 1 +} + +# for canceled status +exit_with_cancel () { + rm -f /tmp/rbkresponse.$$ + echo Canceling Script! + exit 1 +} + +# for undoing status +exit_with_undoing () { + rm -f /tmp/rbkresponse.$$ + echo undoing Script! + exit 1 +} + +check_http_error () { + # All good responses start with a 2 + if [ ${http_response:0:1} != "2" ]; then + echo FATAL: HTTP error from API call: $http_response. The server responded with: + cat /tmp/rbkresponse.$$ ; echo ; exit_with_error + fi +} + +# Given RBK_SID return $db_id of matching database +find_database () { + + # First get IDs of all the mounted DBs for this SID + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount" + rest_api_get + + cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.mountedDatabaseId!=null and .mountedDatabaseName==$SID) | .mountedDatabaseId' > /tmp/mountedDBs.$$ + + # Now get a list of Oracle DBs + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?name=$RBK_SID" + rest_api_get + + # If no dtaabse is found, try with dataguard + if [ `cat /tmp/rbkresponse.$$ | grep "id\":" | wc -l` -eq 0 ]; then + echo " DB not found, try with dataguard..." + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?is_data_guard_group=true&is_relic=false&name=$RBK_SID" + rest_api_get + fi + +#echo "=================================" +#cat /tmp/rbkresponse.$$ | jq -r '.data[]' | tee /tmp/titi +#echo "=================================" +#echo "cat /tmp/rbkresponse.$$ | jq -r '.data[]'" + + + # If no host is specified then just look for the DB with the right SID + if [ -z $RBK_HOST ]; then + + # get list of DB IDs in scope (sid matches and not a relic) + myDBs=$(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID and .isRelic==false) | .id' ; cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID and .isRelic==false) | .dataGuardGroupId' | sort | uniq) + + for db in $myDBs; do + id=$(echo $db | cut -d: -f 4) + if grep -q $id /tmp/mountedDBs.$$; then + continue + else + break + fi + done + + # Get the details for the specific DB ID + read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg ID "OracleDatabase:::$id" '.data[] | select(.id==$ID) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName')) + + # Host was specified + else + read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" --arg HOST "$RBK_HOST" '.data[] | select(.sid==$SID and .infraPath[0].name==$HOST and .isRelic==false) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName')) + fi + + if [ "$dg_type" == "DataGuardMember" ]; then + db_id=$dg_id + # Now find SLA of the DG GROUP not just the DB (which will be unprotected) + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id" + rest_api_get + sla_id=$(cat /tmp/rbkresponse.$$ | jq -r '.effectiveSlaDomainId') + fi + + if [ -z "$db_id" ]; then + echo FATAL: No DB found with SID $RBK_SID on host $RBK_HOST + if [ "${SCRIPT}" = "check_recoverable_range.sh" ] ; then + export ret=11 + else + exit_with_error + fi + else + echo " db_id is: $db_id" + fi +} + +check_get_token () { + + if [ -z "${AUTH_TOKEN}" ]; then + + if [[ "${ID}" =~ ^client ]]; then + # Looks like an RSC service account + id_string=$(echo $ID | cut -d\| -f 2) + else + # Not an RSC service account + id_string=$(echo $ID | cut -d: -f 4) + fi + + # If there is a cached credential file, use it + if [ -f ~/.rbksession.$id_string ]; then + read expiration token < <(echo $(cat ~/.rbksession.$id_string)) + # If token expires within 30 min, get a new one + if [ $($DATE +%s -d $expiration) -lt $(( $($DATE +%s) + 1800 )) ]; then + get_token + else + AUTH_TOKEN=$token + fi + else + get_token + fi + fi +} + +get_token () { + + MYENDPOINT="https://$RUBRIK_IP/api/v1/service_account/session" + MYPAYLOAD="{\"serviceAccountId\":\"$ID\",\"secret\":\"$SECRET\"}" + + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $MYENDPOINT -H "accept: application/json" -H "Content-Type: application/json" -d $MYPAYLOAD) + check_http_error + + AUTH_TOKEN=$(cat /tmp/rbkresponse.$$ | jq -r '.token') + SESSION=$(cat /tmp/rbkresponse.$$ | jq -r '.sessionId') + EXPIRATION=$(cat /tmp/rbkresponse.$$ | jq -r '.expirationTime') + echo "$EXPIRATION $AUTH_TOKEN" > ~/.rbksession.$id_string + +} + +# HTTP GET: Given $ENDPOINT write output to file +rest_api_get () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") + check_http_error +} + +# HTTP POST: Given $ENDPOINT and $PAYLOAD write output to file +rest_api_post () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD) + check_http_error +} + +rest_api_post_empty () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json") + check_http_error +} + +rest_api_patch () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X PATCH $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD) + check_http_error +} + +rest_api_delete () { + check_get_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X DELETE $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") + check_http_error +} + +get_cluster_uuid () { + ENDPOINT="https://$RUBRIK_IP/api/v1/cluster/me" + rest_api_get + cluster_uuid=$(cat /tmp/rbkresponse.$$ | jq -r .id) +} + +# Given an ENDPOINT of an async job, monitor it +check_status () { + if [ $nowait -ne 1 ]; then + # Check the status in a loop + while true; do + rest_api_get + status=$(cat /tmp/rbkresponse.$$ | jq -r '.status') + if [ $status != "SUCCEEDED" ] && [ $status != "FAILED" ] && [ $status != "CANCELED" ] && [ $status != "UNDOING" ]; then + echo Status is $status, checking in 30 seconds + else + if [ $status != "SUCCEEDED" ]; then + + if [ $status = "CANCELED" ] ; then + echo OPERATION FAILED WITH STATUS $status + exit_with_cancel + elif [ $status = "UNDOING" ] ; then + echo OPERATION FAILED WITH STATUS $status + exit_with_undoing + else + echo OPERATION FAILED WITH STATUS $status + exit_with_error + fi + else + echo OPERATION SUCCEEDED + exit 0 + fi + fi + sleep 30 + done + fi +} + +cleanup () { + rm -f /tmp/mountedDBs.$$ + rm -f /tmp/rbkresponse.$$ + rm -f /tmp/payload.$$ +} diff --git a/fromDmOct2025/v930p2/oracle_get_config.sh b/fromDmOct2025/v930p2/oracle_get_config.sh new file mode 100644 index 0000000..b6277ad --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_get_config.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# v0.3 - U701053 - mars 2024 +# +# Shows the current settings for an Oracle DB +# +# usage: oracle_get_config.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h ] [-g] " 1>&2; exit 1; } + +dg=0 + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +if [ $dg -eq 1 ] && [ ! -z ${RBK_HOST+x} ]; then + echo "FATAL: Can't specify a host when targing a DG Group" + exit_with_error +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +find_database + +# API call to list Oracle DB detail +ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id" +rest_api_get + +#echo "file db detail: /tmp/rbkresponse.$$" +# Reads the parts we need + +sla_name=$(cat /tmp/rbkresponse.$$ | jq -r '.effectiveSlaDomainName') +read channels sectionSize log_freq log_retn host_retn rbk_lcluster < <(echo $(cat /tmp/rbkresponse.$$ | jq -r '.numChannels, .sectionSizeInGb, .logBackupFrequencyInMinutes, .logRetentionHours, .hostLogRetentionHours, .isDbLocalToTheCluster')) + +# exit # only db detail + +ENDPOINT=https://$RUBRIK_IP/api/v2/sla_domain/$sla_id +rest_api_get + +read dailyretn monthlyretn starthr startmin < <(echo $(cat /tmp/rbkresponse.$$ | jq -r '.frequencies.daily.retention, .frequencies.monthly.retention, .allowedBackupWindows[].startTimeAttributes.hour, .allowedBackupWindows[].startTimeAttributes.minutes')) + +#echo "file sla: /tmp/rbkresponse.$$" + +echo Protection Details for $RBK_SID on $RBK_HOST +echo DB Local of the $RUBRIK_IP: $rbk_lcluster +echo SLA Name: $sla_name + + +echo SLA Daily Retention: $dailyretn days +echo SLA Monthly Retention: $monthlyretn months +printf "SLA Backup Window: %02d:%02d\n" $starthr $startmin + + +echo Log Backup Frequency: $log_freq minutes +echo Log Backup Retention: $log_retn hours +echo Keep logs on host: $host_retn hours +echo Channels: $channels +echo Section size: $sectionSize + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_get_rr.sh b/fromDmOct2025/v930p2/oracle_get_rr.sh new file mode 100644 index 0000000..162b16c --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_get_rr.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# +# Fetch recoverable ranges for a given Oracle DB +# v0.2 - James Pattinson - August 2021 +# +# usage: oracle_get_rr.sh [-h ] + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h ] [-g|] " 1>&2; exit 1; } + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +find_database + +echo Fetching Recoverable Ranges for $RBK_SID on $RBK_HOST + +# API call to get the recoverable range +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/recoverable_range" +rest_api_get + +echo + +#echo -e "SID\t Start Time\t\t\tEnd Time\t\t\tStatus" +#echo -e "-------- ----------\t\t\t--------\t\t\t------" +echo -e "Start Time\t\t\tEnd Time\t\t\tStatus" +echo -e "----------\t\t\t--------\t\t\t------" + +RESULT_GET=`cat /tmp/rbkresponse.$$ | jq -r '.data[]' | jq -r ' "\(.beginTime)\t\(.endTime)\t\(.status)"'` +# echo "$RBK_SID ${RESULT_GET}" +echo "${RESULT_GET}" + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_get_sla_config.sh b/fromDmOct2025/v930p2/oracle_get_sla_config.sh new file mode 100644 index 0000000..5929f9e --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_get_sla_config.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - June 2022 +# +# Shows the current settings for an Oracle DB +# +# usage: oracle_get_config.sh +# ----------------------------------------------------------------------------- +# Version: Autor: Date: Descrpition: +# -------- ------ ----- ------------ +# 1.0.0.0 James 04.07.23 Create +# 1.0.0.1 U701053 09.06.23 add Section size +# 1.0.0.2 U701053 19.06.23 add the onformations for porepo1 +# ----------------------------------------------------------------------------- +MYDIR="$(dirname "$(realpath "$0")")" +#source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo ""; echo "Usage: $0 [-c for porepo1] [-h ] "; echo "" 1>&2; exit 1; } +CATALOG=no +dg=0 + +while getopts "ch:" o; do + case "${o}" in + c) + CATALOG=yes + ;; + h) + RBK_HOST=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +if [ $dg -eq 1 ] && [ ! -z ${RBK_HOST+x} ]; then + echo "FATAL: Can't specify a host when targing a DG Group" + exit_with_error +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +find_database + +# API call to list Oracle DB detail +ENDPOINT=https://$RUBRIK_IP/api/v1/oracle/db/$db_id +rest_api_get + +# Reads the parts we need +sla_name=$(cat /tmp/rbkresponse.$$ | jq -r '.effectiveSlaDomainName') +echo "Original SLA-Name: ${sla_name}" +sla_name=${sla_name%' (Managed by Polaris)'} + +read id dbUniqueName channels log_freq log_retn host_retn section_Size_Gb < <(echo $(cat /tmp/rbkresponse.$$ | jq -r '.id, .dbUniqueName, .numChannels, .logBackupFrequencyInMinutes, .logRetentionHours, .hostLogRetentionHours, .sectionSizeInGb')) +# echo "channels: $channels, log_freq: $log_freq, log_retn: $log_retn, host_retn: $host_retn, Sectio size: $section_Size_Gb Gb" + +#echo "rbkresponse /tmp/rbkresponse.$$" +#echo "================================================" +#cat /tmp/rbkresponse.$$ +#echo "================================================" +ENDPOINT=https://$RUBRIK_IP/api/v2/sla_domain/$sla_id +rest_api_get + +read dailyretn monthlyretn starthr startmin < <(echo $(cat /tmp/rbkresponse.$$ | jq -r '.frequencies.daily.retention, .frequencies.monthly.retention, .allowedBackupWindows[].startTimeAttributes.hour, .allowedBackupWindows[].startTimeAttributes.minutes')) + +#echo "================================================" +#cat /tmp/rbkresponse.$$ +#echo "================================================" +echo +echo Protection Details for $RBK_SID on $RBK_HOST +echo SLA Name: $sla_name +echo SLA Daily Retention: $dailyretn days +echo SLA Monthly Retention: $monthlyretn months +printf "SLA Backup Window: %02d:%02d\n" $starthr $startmin +echo SLA Log Backup Frequency: $log_freq minutes +echo SLA Log Backup Retention: $log_retn hours +if [ $host_retn -eq -2 ]; then + echo SLA Keep logs on host: Skip Deletion +elif [ $host_retn -eq -1 ]; then + echo SLA Keep logs on host: None, deleted immediately +else + echo SLA Keep logs on host: $host_retn hours +fi +echo Section size: $section_Size_Gb Gb +echo Channels: $channels + +if [ "${CATALOG}" = "yes" ] ; then + if [ "$monthlyretn" = "null" ] ; then + monthlyretn="" + fi + if [ "$dailyretn" = "null" ] ; then + dailyretn="" + fi + echo "DETAILS-SLA:$RBK_SID;$(printf "%-12s\n" `hostname -s`);$id;$RBK_HOST;`printf "%-17s\n" $dbUniqueName`;`printf "%-22s\n" $sla_name`;$dailyretn;$monthlyretn;`printf "%02d:%02d\n" $starthr $startmin`;$log_freq;$log_retn;$host_retn;$section_Size_Gb;$channels" +fi +cleanup + diff --git a/fromDmOct2025/v930p2/oracle_last_backup.sh b/fromDmOct2025/v930p2/oracle_last_backup.sh new file mode 100644 index 0000000..38fff05 --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_last_backup.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Lists the registered DBs for a given Oracle Host or RAC +# and their assigned SLAs +# +# usage: oracle_list_db.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +# Given RBK_SID return $db_id of matching database +find_database1 () { + + # First get IDs of all the mounted DBs for this SID + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount" + rest_api_get + + cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.mountedDatabaseId!=null and .mountedDatabaseName==$SID) | .mountedDatabaseId' > /tmp/mountedDBs.$$ + + # Now get a list of Oracle DBs + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?name=$RBK_SID" + rest_api_get + + # If no host is specified then just look for the DB with the right SID + if [ -z $RBK_HOST ]; then + + # get list of DB IDs in scope (sid matches and not a relic) + myDBs=$(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID and .isRelic==false) | .id' ; cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID and .isRelic==false) | .dataGuardGroupId' | sort | uniq) + + for db in $myDBs; do + id=$(echo $db | cut -d: -f 4) + if grep -q $id /tmp/mountedDBs.$$; then + continue + else + break + fi + done + + # Get the details for the specific DB ID + read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg ID "OracleDatabase:::$id" '.data[] | select(.id==$ID) | .name, .id, .configuredSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName')) + + # Host was specified + else + read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" --arg HOST "$RBK_HOST" '.data[] | select(.sid==$SID and .infraPath[0].name==$HOST and .isRelic==false) | .name, .id, .configuredSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName')) + fi + + if [ "$dg_type" == "DataGuardMember" ]; then + db_id=$dg_id + fi + + if [ -z "$db_id" ]; then + echo FATAL: No DB found with SID $RBK_SID on host $RBK_HOST + #exit_with_error + fi +} + +# HTTP GET: Given $ENDPOINT write output to file +rest_api_get1 () { + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") + #check_http_error +} + + + + +usage() { echo "Usage: $0 [-h ] [-g|] " 1>&2; exit 1; } + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +#echo "Fetching available snapshots for \"$RBK_SID\" on $RBK_HOST" +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +find_database1 + +echo Fetching available snapshots for $RBK_SID on $RBK_HOST + +# API call to get the recoverable range +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/snapshot" +rest_api_get1 + + +#cat /tmp/rbkresponse.$$ | jq -r '.data | sort_by(.date) | .[] | "\(.date)\t\(.slaName)"' | grep 2021-11-26 +if [ -z "`cat /tmp/rbkresponse.$$ | jq -r '.data | sort_by(.date) | .[] | "\(.date)\t\(.slaName)"'`" ] ; then + echo "last backup: ${RBK_SID} `hostname -s` 0001-01-01T00:00:00.000Z Problem-or-No-Backup No-info No-info" + if [ ! -z "${INFO_PROBLEM}" ] ; then + echo "${INFO_PROBLEM}" + fi +else + echo "last backup: ${RBK_SID} `hostname -s` `cat /tmp/rbkresponse.$$ | jq -r '.data | sort_by(.date) | .[] | "\(.date)\t\(.slaName)\t\(.isOnDemandSnapshot)\t\(.replicationLocationIds)"' | tail -1`" +fi + +cleanup + diff --git a/fromDmOct2025/v930p2/oracle_list_backup.sh b/fromDmOct2025/v930p2/oracle_list_backup.sh new file mode 100644 index 0000000..23b819b --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_list_backup.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Lists the registered DBs for a given Oracle Host or RAC +# and their assigned SLAs +# +# usage: oracle_list_db.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h ] [-g|] " 1>&2; exit 1; } + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +find_database + +echo Fetching available snapshots for $RBK_SID on $RBK_HOST + +# API call to get the recoverable range +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/snapshot" +rest_api_get + +echo + +echo -e "Sid\t\tDate Taken\t\t\tOn Demand\tFreq\tSLA Name\t\treplication" +echo -e "--------\t----------\t\t\t---------\t-----\t----------\t\t-----------" + +cat /tmp/rbkresponse.$$ | jq -r '.data | sort_by(.date) | .[] | "\(.databaseName)\t\(.date)\t\(.isOnDemandSnapshot)\t\t\(.snapshotRetentionInfo.localInfo.snapshotFrequency)\t\(.slaName)\t\(.snapshotRetentionInfo.replicationInfos[0].id)\t\(.snapshotRetentionInfo.replicationInfos[0].name)"' + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_list_db.sh b/fromDmOct2025/v930p2/oracle_list_db.sh new file mode 100644 index 0000000..cf094ac --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_list_db.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Lists the registered DBs for a given Oracle Host or RAC +# and their assigned SLAs +# +# usage: oracle_list_db.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +RBK_HOST=$1 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db" + +rest_api_get + +echo -e "SID\t\tSLA\t\t\tArchivelogMode\tDG Type\t\tDG Group" +echo -e "---\t\t---\t\t\t--------------\t-------\t\t--------" +cat /tmp/rbkresponse.$$ | jq -r --arg HOST $RBK_HOST '.data[] | select(.infraPath[0].name==$HOST and .isRelic==false) | {sid,effectiveSlaDomainName,isArchiveLogModeEnabled,dataGuardType,dataGuardGroupName} ' | jq -r ' "\(.sid)\t\(.effectiveSlaDomainName)\t\t\(.isArchiveLogModeEnabled)\t\t\(.dataGuardType)\t\(.dataGuardGroupName)"' + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_list_dg.sh b/fromDmOct2025/v930p2/oracle_list_dg.sh new file mode 100644 index 0000000..17ffcbf --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_list_dg.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Lists the registered DBs for a given Oracle Host or RAC +# and their assigned SLAs +# +# usage: oracle_list_dg.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?is_data_guard_group=true&is_relic=false" + +rest_api_get + +echo -e "SID\t\tSLA\t\t\t\tArchivelogMode\tDG Type\t\tDG Group" +echo -e "---\t\t---\t\t\t\t--------------\t-------\t\t--------" +cat /tmp/rbkresponse.$$ | jq -r '.data[] | {name,effectiveSlaDomainName,isArchiveLogModeEnabled,dataGuardType,dbUniqueName} ' | jq -r ' "\(.name)\t\(.effectiveSlaDomainName)\t\t\t\(.isArchiveLogModeEnabled)\t\t\(.dataGuardType)\t\(.dbUniqueName)"' + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_list_dg_details.sh b/fromDmOct2025/v930p2/oracle_list_dg_details.sh new file mode 100644 index 0000000..baf887a --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_list_dg_details.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Lists the registered DBs for a given Oracle Host or RAC +# and their assigned SLAs +# +# usage: oracle_list_dg.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?is_data_guard_group=true&is_relic=false" + +rest_api_get + +echo -e "ID\t\t\t\t\t\t\tSID\t\tRelic\tdb local\tSLA\t\t\tSLA last update\t\t\tSLA-lock\tArlog\tDG Type\t\tDG Group\t\tfreq\tRet host\tDG Group" +echo -e "---\t\t\t\t\t\t\t---\t\t-----\t--------\t-------------------\t-----------------\t\t----------\t-----\t---------\t----------\t\t----\t--------\t----------" +cat /tmp/rbkresponse.$$ | jq -r '.data[] | {id,name,isRelic,isDbLocalToTheCluster,effectiveSlaDomainName,slaLastUpdateTime,isConfiguredSlaDomainRetentionLocked,isArchiveLogModeEnabled,dataGuardType,dbUniqueName,logBackupFrequencyInMinutes,hostLogRetentionHours,dataGuardGroupMembers}' | jq -r ' "\(.id)\t\(.name)\t\(.isRelic)\t\(.isDbLocalToTheCluster)\t\t\(.effectiveSlaDomainName)\t\(.slaLastUpdateTime)\t\(.isConfiguredSlaDomainRetentionLocked)\t\t\(.isArchiveLogModeEnabled)\t\(.dataGuardType)\t\(.dbUniqueName)\t\(.logBackupFrequencyInMinutes)\t\(.hostLogRetentionHours)\t\t\(.dataGuardGroupMembers)"' +#cat /tmp/rbkresponse.$$ | jq -r '.data[] | {name,effectiveSlaDomainName,isArchiveLogModeEnabled,dataGuardType,dbUniqueName} ' | jq -r ' "\(.name)\t\(.effectiveSlaDomainName)\t\t\t\(.isArchiveLogModeEnabled)\t\t\(.dataGuardType)\t\(.dbUniqueName)"' + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_list_mounts.sh b/fromDmOct2025/v930p2/oracle_list_mounts.sh new file mode 100644 index 0000000..9ea46b2 --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_list_mounts.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Lists any Oracle Live Mounts present +# +# usage: oracle_list_db.sh [dbname] +# if no hostname specified, will list them all + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +if [ $# -gt 1 ]; then + echo "Usage: $0 [dbname]" + exit 1 +fi + +dbname=$1 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Mounted Oracle DBs +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount?source_database_name=$dbname" + +rest_api_get + +echo Live Mounts +echo +echo -e "Source DB\t\tTarget\t\t\t\tFiles Only\tStatus\t\tMount ID\t\t\t\tCreation Date\t\t\tOwner" +echo -e "---------\t\t------\t\t\t\t----------\t------\t\t--------\t\t\t\t-------------\t\t\t-------------------" + + +cat /tmp/rbkresponse.$$ | jq -r '.data[]' | jq -r ' "\(.sourceDatabaseName)\t\t\(.targetHostname)\t\(.isFilesOnlyMount)\t\t\(.status)\t\(.id)\t\(.creationDate)\t\(.ownerName)"' + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_list_sla.sh b/fromDmOct2025/v930p2/oracle_list_sla.sh new file mode 100644 index 0000000..99f3eaf --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_list_sla.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# +# Example RSC API call script for Die Mobiliar +# v0.1 - James Pattinson - June 2024 +# +# Lists Global SLAs from RSC which support Oracle +# +# usage: rsc_list_slas.sh [filter] + +usage() { echo "Usage: $0 [filter]" 1>&2; exit 1; } + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh +source $MYDIR/rsc_ops.sh + +gql_SLAListQuery='query SLAListQuery($after: String, $first: Int, $filter: [GlobalSlaFilterInput!], $sortBy: SlaQuerySortByField, $sortOrder: SortOrder) { + slaDomains( + after: $after + first: $first + filter: $filter + sortBy: $sortBy + sortOrder: $sortOrder + ) { + edges { + node { + name + ... on GlobalSlaReply { + id + objectTypes + __typename + } + } + } + } +}' + +filter=$1 + +variables="{ + \"shouldShowPausedClusters\":true, + \"filter\":[{\"field\":\"NAME\",\"text\":\"$filter\"},{\"field\":\"OBJECT_TYPE\",\"objectTypeList\":[\"ORACLE_OBJECT_TYPE\"]}], + \"sortBy\":\"NAME\", + \"sortOrder\":\"ASC\", + \"first\":50 + }" + +gqlQuery="$(echo $gql_SLAListQuery)" +gqlVars="$(echo $variables)" +rsc_gql_query + +cat /tmp/rbkresponse.$$ | jq -r '.data.slaDomains.edges[] | .node.name' + +cleanup \ No newline at end of file diff --git a/fromDmOct2025/v930p2/oracle_mount.sh b/fromDmOct2025/v930p2/oracle_mount.sh new file mode 100644 index 0000000..a26348b --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_mount.sh @@ -0,0 +1,137 @@ +#!/bin/bash +# +# Perform a Live Mount of an Oracle DB +# v0.2 - James Pattinson - August 2021 +# +# usage: oracle_mount.sh [-h ] [-d [-f] <"timestamp"> +# +# -d specify $ORACLE_HOME on target - needed for mount of Data Guard DBs +# -f mount files only - do not create database +# +# Timestamp YYYY-MM-DD HH:MM:SS +# Time is passed to 'date' on THIS machine, will use local timezone +#---------------------------------------------------------------------------------------- +# Version: Autor: Date: Descrpition: +# -------- ------ ----- ------------ +# 1.0.0.0 U701053 05.04.23 Modification the search of target_id +# When we mount a live mount on the production clusters, rubrik returns the 2 lines +# (2 possibilities) and the script did not know which one to choose) +# 1.0.0.1 U701053 07.02.25 Modification of the command to find the live mount id (RBK_ID_LV) +#---------------------------------------------------------------------------------------- + + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h ] [-d [-f|-n] <\"timestamp\">" 1>&2 + echo "Format Timestamp YYYY-MM-DD HH:MM:SS" + exit 1; } + +filesonly=false + +while getopts "h:d:f" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + f) + filesonly=true + ;; + d) + oraclehome=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +RBK_SID=$1 +RBK_TGT=$2 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +find_database + +# API call to get the host ID of the target +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/host?name=$RBK_TGT" +rest_api_get + +total=$(cat /tmp/rbkresponse.$$ | jq -r .total) +if [ $total -ne 1 ]; then + echo Target host name of $RBK_TGT does not map to a single host: + cat /tmp/rbkresponse.$$ | jq -r '.data[].name' +fi + +#echo "##############################################" +#cat /tmp/rbkresponse.$$ +#echo "##############################################" + +target_id=$(cat /tmp/rbkresponse.$$ | jq -r '.data[0].id') +echo " Target_id : $target_id" + +# convert datestamp from string into milliseconds +datestring=$3 + +echo requested timestamp is $datestring + +ts=$(date -d"$datestring" +%s) +if [ $? -ne 0 ]; then + echo Problem with timestamp + exit_with_error +fi +((millis = $ts * 1000)) + +if [ ! -z ${oraclehome+x} ]; then + configmap="\"ORACLE_HOME\":\"$oraclehome\"" +fi + +# API call to perform the mount +PAYLOAD="{\"recoveryPoint\":{\"timestampMs\":$millis},\"targetOracleHostOrRacId\":\"$target_id\",\"targetMountPath\":\"/rbk/\",\"shouldMountFilesOnly\":$filesonly,\"advancedRecoveryConfigMap\":{$configmap}}" +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/mount" + +rest_api_post + +ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href') +LOOP=0 +while true; do + rest_api_get + status=$(cat /tmp/rbkresponse.$$ | jq -r '.status') + if [ $status != "SUCCEEDED" ] && [ $status != "FAILED" ]; then + echo Status is $status, checking in 10 seconds + if [ $status = "RUNNING" ] && [ ${LOOP} -ne 1 ] ; then + LOOP=1 + sleep 5 + save=$ENDPOINT + ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount?source_database_name=$dbname" + rest_api_get + # cat /tmp/rbkresponse.$$ | jq -r '.data[]' + cat /tmp/rbkresponse.$$ | jq -r '.data[] | "\(.id), \(.status), \(.sourceDatabaseName), \(.creationDate)"' | grep Mounting | grep ${RBK_SID} | sort -k 4 + #RBK_ID_LV=$(cat /tmp/rbkresponse.$$ | jq -r '.data[] | select(.status=="Mounting") | .id') + RBK_ID_LV=`cat /tmp/rbkresponse.$$ | jq -r '.data[] | "\(.id), \(.status), \(.sourceDatabaseName), \(.creationDate)"' | grep Mounting | grep ${RBK_SID} | sort -k 4 | tail -1 | awk '{print $1}' | sed 's/,$//'` + ENDPOINT=$save + fi + else + if [ $status != "SUCCEEDED" ]; then + echo LIVE MOUNT FAILED WITH STATUS $status + exit_with_error + else + echo LIVE MOUNT SUCCEEDED + echo "The live mount id is: ${RBK_ID_LV}" + # cat /tmp/rbkresponse.$$ | jq -r ' ' + exit 0 + fi + fi + sleep 10 +done + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_set_channel.sh b/fromDmOct2025/v930p2/oracle_set_channel.sh new file mode 100644 index 0000000..95ebd29 --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_set_channel.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Set the backup settings for a given Oracle DB +# +# usage: oracle_set_config.sh +# +# Log backup of 0 disables log backup +# host retention of -1 disables host log retention + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h ] " 1>&2; exit 1; } + +dg=0 + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +channels=$2 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to get DB details +find_database + +# API call to set configuration + +if [ "$dg_type" == "DataGuardMember" ]; then + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/data_guard_group/$db_id" +else + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id" +fi +PAYLOAD={\"numChannels\":$channels} + +rest_api_patch + +echo New configuration for $RBK_SID on $RBK_HOST is set + +cleanup + diff --git a/fromDmOct2025/v930p2/oracle_set_config.sh b/fromDmOct2025/v930p2/oracle_set_config.sh new file mode 100644 index 0000000..61ad4be --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_set_config.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Set the backup settings for a given Oracle DB +# +# usage: oracle_set_config.sh +# +# Log backup of 0 disables log backup +# host retention of -1 disables host log retention + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h ] " 1>&2; exit 1; } + +dg=0 + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +# log_freq=$2 +#log_retn=$2 +#host_retn=$3 +channels=$2 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to get DB details +find_database + +# API call to set configuration + +if [ "$dg_type" == "DataGuardMember" ]; then + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/data_guard_group/$db_id" +else + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id" +fi +# PAYLOAD={\"logBackupFrequencyInMinutes\":$log_freq,\"logRetentionHours\":$log_retn,\"hostLogRetentionHours\":$host_retn,\"numChannels\":$channels} +PAYLOAD={\"numChannels\":$channels} + +rest_api_patch + +echo New configuration for $RBK_SID on $RBK_HOST is set + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_set_msection_size.sh b/fromDmOct2025/v930p2/oracle_set_msection_size.sh new file mode 100644 index 0000000..7c63ec8 --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_set_msection_size.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# Set the backup settings for a given Oracle DB +# +# usage: oracle_set_config.sh +# +# Log backup of 0 disables log backup +# host retention of -1 disables host log retention + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h ] " 1>&2; exit 1; } + +dg=0 + +while getopts "h:" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +SECTION_SIZE_GB=$2 + +if [ "${SECTION_SIZE_GB}" != "enable" ] && [ "${SECTION_SIZE_GB}" != "disable" ] ; then + echo "" + echo "Sorry the parameter of this script is not good ...." + usage + exit 1 +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to get DB details +find_database + +# API call to set configuration + +if [ "$dg_type" == "DataGuardMember" ]; then + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/data_guard_group/$db_id" +else + ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id" +fi + +if [ "${SECTION_SIZE_GB}" = "enable" ] ; then + SECTION_SIZE_GB="500" +else + SECTION_SIZE_GB="-1" +fi + +PAYLOAD={\"sectionSizeInGb\":$SECTION_SIZE_GB} + +rest_api_patch + +echo New configuration for $RBK_SID on $RBK_HOST is set to $SECTION_SIZE_GB for the section size + +cleanup + diff --git a/fromDmOct2025/v930p2/oracle_sla_log_config.sh b/fromDmOct2025/v930p2/oracle_sla_log_config.sh new file mode 100644 index 0000000..295d1f8 --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_sla_log_config.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.3 - James Pattinson - June 2022 +# +# Set the backup settings for a given Oracle DB +# +# usage: oracle_set_config.sh +# +# Log backup of 0 disables log backup +# host retention of -1 disables host log retention + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs_new.sh + +usage() { echo "Usage: $0 -s -f -r -h " 1>&2; echo ""; exit 1; } + +dg=0 + +while getopts "s:f:r:h:" o; do + case "${o}" in + s) + RBK_SLA=${OPTARG} + ;; + f) + log_freq=${OPTARG} + ;; + r) + log_retn=${OPTARG} + ;; + h) + host_retn=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +#RBK_SLA=$1 + +if [ -z "${RBK_SLA}" ] || [ -z "${log_freq}" ] || [ -z "${log_retn}" ] || [ -z "${host_retn}" ]; then + echo "" + usage + echo "" +fi + +#log_freq=$2 +#log_retn=$3 +#host_retn=$4 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# Encode the SLA name for curl +RBK_SLA_SAFE=$(printf %s "${RBK_SLA}" |jq -sRr @uri) + +# API call to list SLAs +ENDPOINT=https://$RUBRIK_IP/api/v1/sla_domain?name=$RBK_SLA_SAFE +rest_api_get + +total=$(cat /tmp/rbkresponse.$$ | jq -r '.total') + if [ $total -ne 1 ]; then + echo SLA not found, or more than one SLA matches input of \"$RBK_SLA\" + echo Please run again and specify one of: + cat /tmp/rbkresponse.$$ | jq -r '.data[].name' + exit_with_error + fi + +sla_id=$(cat /tmp/rbkresponse.$$ | jq -r '.data[0].id') + +# API call to set configuration + +#PAYLOAD={\"logBackupFrequencyInMinutes\":$log_freq,\"logRetentionHours\":$log_retn,\"hostLogRetentionHours\":$host_retn,\"numChannels\":$channels} +#PAYLOAD={\"numChannels\":$channels,\"hasLogConfigFromSla\":true} + +((logrtn_min = $log_retn * 60 * 24)) +if [ $host_retn -gt 0 ]; then + ((hostrtn_min = $host_retn * 60)) +else + hostrtn_min=$host_retn +fi +echo "titi" +ENDPOINT=https://$RUBRIK_IP/api/v2/sla_domain/${sla_id}?should_apply_to_existing_snapshots=false&should_apply_to_non_policy_snapshots=false + +echo "titi" +PAYLOAD="{\"logConfig\":{},\"logConfigs\":{\"OracleDatabase\":{\"slaLogFrequencyConfig\":{\"logFrequencyType\":\"Minute\",\"retention\":$logrtn_min,\"freqency\":$log_freq},\"hostLogRetentionInMinutes\":$hostrtn_min}}}" + +echo "titi" +rest_api_patch +echo "titi" + +echo New configuration for $RBK_SID on $RBK_HOST is set + +cleanup diff --git a/fromDmOct2025/v930p2/oracle_validate.sh b/fromDmOct2025/v930p2/oracle_validate.sh new file mode 100644 index 0000000..0d6ddf4 --- /dev/null +++ b/fromDmOct2025/v930p2/oracle_validate.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# +# Perform a validation of an Oracle DB backup +# v0.2 - James Pattinson - August 2021 +# +# usage: oracle_validate.sh <"timestamp"> [sgasizeMB] +# +# Timestamp YYYY-MM-DD HH:MM:SS +# Time is passed to 'date' on THIS machine, will use local timezone +# +# SGA size defaults to 30% of target host RAM if size in MB is not specified + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +usage() { echo "Usage: $0 [-h ] [-n] [-s sgasizeMB] <"timestamp">" 1>&2; exit 1; } + +while getopts "h:s:n" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + s) + sgasizeMB=${OPTARG} + ;; + n) + nowait=1 + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +RBK_SID=$1 +RBK_TGT=$2 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to list Oracle DBs +find_database + +# API call to get the host ID of the target +ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/host?name=$RBK_TGT" +http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") +check_http_error + +total=$(cat /tmp/rbkresponse.$$ | jq -r .total) +if [ $total -ne 1 ]; then + echo Target host name of $RBK_TGT does not map to a single host: + cat /tmp/rbkresponse.$$ | jq -r '.data[].name' + exit_with_error +fi + +target_id=$(cat /tmp/rbkresponse.$$ | jq -r '.data[0].id') + +# convert datestamp from string into milliseconds +datestring=$3 + +echo requested timestamp is $datestring + +ts=$(date -d"$datestring" +%s) +if [ $? -ne 0 ]; then + echo Problem with timestamp + exit_with_error +fi +((millis = $ts * 1000)) + +# API call to perform the validation + +# is SGA size specified? +if [ -z $sgasizeMB ]; then + PAYLOAD="{\"recoveryPoint\":{\"timestampMs\":$millis},\"targetOracleHostOrRacId\":\"$target_id\"}" +else + PAYLOAD="{\"recoveryPoint\":{\"timestampMs\":$millis},\"targetOracleHostOrRacId\":\"$target_id\",\"sgaMaxSizeInMb\":$sgasizeMB}" +fi + +echo Requesting validation for $RBK_SID on target host $RBK_TGT + +ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id/validate" + +rest_api_post + +# Check the status in a loop. Translation of link using sed because API returns wrong href! +ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href' | sed 's/v1/internal/') +check_status +cleanup diff --git a/fromDmOct2025/v930p2/refresh_host.sh b/fromDmOct2025/v930p2/refresh_host.sh new file mode 100644 index 0000000..30d0320 --- /dev/null +++ b/fromDmOct2025/v930p2/refresh_host.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# +# Example API call script for Die Mobiliar +# v0.2 - James Pattinson - August 2021 +# +# usage: refresh_host.sh + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +RBK_HOST=$1 + +echo Connecting to Rubrik with IP $RUBRIK_IP + +# API call to get host details +ENDPOINT="https://$RUBRIK_IP/api/v1/host?name=$RBK_HOST" +rest_api_get + +total=$(cat /tmp/rbkresponse.$$ | jq -r .total) +if [ $total -ne 1 ]; then + echo Host name of $RBK_HOST does not map to a single host: + cat /tmp/rbkresponse.$$ | jq -r '.data[].name' + exit_with_error +fi + +host_id=$(cat /tmp/rbkresponse.$$ | jq -r '.data[0].id') + +if [ -z $host_id ]; then + echo FATAL: Unable to map host name to ID + exit_with_error +fi + +# API call to assign SLA +ENDPOINT="https://$RUBRIK_IP/api/v1/host/$host_id/refresh" + +echo Requesting host refresh for $RBK_HOST + +rest_api_post_empty + +echo Refreshed host details for $RBK_HOST + +cleanup diff --git a/fromDmOct2025/v930p2/rsc_assign_sla.sh b/fromDmOct2025/v930p2/rsc_assign_sla.sh new file mode 100644 index 0000000..37cf6d5 --- /dev/null +++ b/fromDmOct2025/v930p2/rsc_assign_sla.sh @@ -0,0 +1,138 @@ +#!/bin/bash +# +# v0.3 - James Pattinson - Feb 2025 +# +# usage: rsc_assign_sla.sh [-h ] [-c | -d] [sla name] +# +# If SLA name contains spaces then use quotes around it +# +# -c Clear any direct assignment +# -d Do Not Protect (Override any higher SLA assignment) + +MYDIR="$(dirname "$(realpath "$0")")" +#source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh +source $MYDIR/rsc_ops.sh + +usage() { echo "Usage: $0 [-h ] <-c | -d | sla name>" 1>&2; exit 1; } + +dg=0 + +SLA_OP="protectWithSlaId" +existingSnapshotRetention="NOT_APPLICABLE" + +while getopts "h:cd" o; do + case "${o}" in + h) + RBK_HOST=${OPTARG} + ;; + c) + SLA_OP="noAssignment" + ;; + d) + SLA_OP="doNotProtect" + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +RBK_SID=$1 +RBK_SLA=$2 + +if [ -z "${RBK_SID}" ]; then + usage +fi + +echo Connecting to Rubrik with IP $RUBRIK_IP + +if [ "$SLA_OP" != 'protectWithSlaId' ]; then + new_sla_id=null + RBK_SLA=$SLA_OP + if [ "$SLA_OP" == 'doNotProtect' ]; then + existingSnapshotRetention="RETAIN_SNAPSHOTS" + fi +else + gql_SLAListQuery='query SLAListQuery($after: String, $first: Int, $filter: [GlobalSlaFilterInput!], $sortBy: SlaQuerySortByField, $sortOrder: SortOrder) { + slaDomains( + after: $after + first: $first + filter: $filter + sortBy: $sortBy + sortOrder: $sortOrder + ) { + edges { + node { + name + ... on GlobalSlaReply { + id + objectTypes + __typename + } + } + } + } +}' + + filter=$RBK_SLA + + variables="{ + \"shouldShowPausedClusters\":true, + \"filter\":[{\"field\":\"NAME\",\"text\":\"$filter\"},{\"field\":\"OBJECT_TYPE\",\"objectTypeList\":[\"ORACLE_OBJECT_TYPE\"]}], + \"sortBy\":\"NAME\", + \"sortOrder\":\"ASC\", + \"first\":50 + }" + + gqlQuery="$(echo $gql_SLAListQuery)" + gqlVars="$(echo $variables)" + rsc_gql_query + + #cat /tmp/rbkresponse.$$ + + new_sla_id=$(cat /tmp/rbkresponse.$$ | jq --arg SLA "$RBK_SLA" -r '.data.slaDomains.edges[] | select(.node.name == $SLA) | .node.id') + new_sla_id=\"${new_sla_id}\" +fi + +if [ -z $new_sla_id ]; then + echo FATAL: Unable to map SLA ID for $RBK_SLA + exit_with_error +else + echo "INFO: SLA ID for $RBK_SLA is $new_sla_id" +fi + +rsc_find_database +echo "INFO: DB found $rsc_db_id which is a $database_type instance" + +gql_AssignSlaMutation='mutation AssignSla($input: AssignSlaInput!) { + assignSla(input: $input) { + success + __typename + } +}' + +variables="{ + \"input\": { + \"objectIds\": [ + \"$rsc_db_id\" + ], + \"slaDomainAssignType\": \"$SLA_OP\", + \"slaOptionalId\": $new_sla_id, + \"existingSnapshotRetention\": \"$existingSnapshotRetention\", + \"shouldApplyToExistingSnapshots\": false, + \"shouldApplyToNonPolicySnapshots\": false + } + }" + +gqlQuery="$(echo $gql_AssignSlaMutation)" +gqlVars="$(echo $variables)" +rsc_gql_query + +cat /tmp/rbkresponse.$$ | jq -r + +echo Assigned $RBK_SLA to $RBK_SID + +cleanup + diff --git a/fromDmOct2025/v930p2/rsc_list_oracle_slas.sh b/fromDmOct2025/v930p2/rsc_list_oracle_slas.sh new file mode 100644 index 0000000..99f3eaf --- /dev/null +++ b/fromDmOct2025/v930p2/rsc_list_oracle_slas.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# +# Example RSC API call script for Die Mobiliar +# v0.1 - James Pattinson - June 2024 +# +# Lists Global SLAs from RSC which support Oracle +# +# usage: rsc_list_slas.sh [filter] + +usage() { echo "Usage: $0 [filter]" 1>&2; exit 1; } + +MYDIR="$(dirname "$(realpath "$0")")" +# source $MYDIR/rbk_api.conf +source $MYDIR/oracle_funcs.sh +source $MYDIR/rsc_ops.sh + +gql_SLAListQuery='query SLAListQuery($after: String, $first: Int, $filter: [GlobalSlaFilterInput!], $sortBy: SlaQuerySortByField, $sortOrder: SortOrder) { + slaDomains( + after: $after + first: $first + filter: $filter + sortBy: $sortBy + sortOrder: $sortOrder + ) { + edges { + node { + name + ... on GlobalSlaReply { + id + objectTypes + __typename + } + } + } + } +}' + +filter=$1 + +variables="{ + \"shouldShowPausedClusters\":true, + \"filter\":[{\"field\":\"NAME\",\"text\":\"$filter\"},{\"field\":\"OBJECT_TYPE\",\"objectTypeList\":[\"ORACLE_OBJECT_TYPE\"]}], + \"sortBy\":\"NAME\", + \"sortOrder\":\"ASC\", + \"first\":50 + }" + +gqlQuery="$(echo $gql_SLAListQuery)" +gqlVars="$(echo $variables)" +rsc_gql_query + +cat /tmp/rbkresponse.$$ | jq -r '.data.slaDomains.edges[] | .node.name' + +cleanup \ No newline at end of file diff --git a/fromDmOct2025/v930p2/rsc_ops.sh b/fromDmOct2025/v930p2/rsc_ops.sh new file mode 100644 index 0000000..875c4c2 --- /dev/null +++ b/fromDmOct2025/v930p2/rsc_ops.sh @@ -0,0 +1,322 @@ +#!/bin/bash +# +#-------------------------------------------------------------------------------------------------------- +# RSC shell script support functions +# v0.2 - James Pattinson - August 2021 +# v0.3 - U701053 - 30.03.2022 - if database not found, try to search with the ENDPOINT datagurad +# v0.4 - James Pattinson 25/01/23 - Adding support for Service Accounts +#-------------------------------------------------------------------------------------------------------- + +#MYDIR="$(dirname "$(realpath "$0")")" +#source $MYDIR/rbk_api.conf + +check_get_rsc_token () { + + if [ -z "${RSC_AUTH_TOKEN}" ]; then + + if [[ "${ID}" =~ ^client ]]; then + # Looks like an RSC service account + id_string=$(echo $ID | cut -d\| -f 2) + else + # Not an RSC service account + exit_with_error + fi + + # If there is a cached credential file, use it + if [ -f ~/.rbkRscsession.$id_string ]; then + read expiration token < <(echo $(cat ~/.rbkRscsession.$id_string)) + # If token expires within 30 min, get a new one + if [ $expiration -lt $(( $($DATE +%s) + 1800 )) ]; then + get_rsc_token + else + RSC_AUTH_TOKEN=$token + fi + else + get_rsc_token + fi + fi +} + +get_rsc_token () { + + MYENDPOINT="https://${RSC_HOST}/api/client_token" + MYPAYLOAD="{\"client_id\":\"$ID\",\"client_secret\":\"$SECRET\"}" + + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $MYENDPOINT -H "accept: application/json" -H "Content-Type: application/json" -d $MYPAYLOAD) + check_http_error + + RSC_AUTH_TOKEN=$(cat /tmp/rbkresponse.$$ | jq -r '.access_token') + SECONDS=$(cat /tmp/rbkresponse.$$ | jq -r '.expires_in') + EXPIRATION=$($DATE +%s -d "+${SECONDS} seconds") + #cat /tmp/rbkresponse.$$ | jq + echo "$EXPIRATION $RSC_AUTH_TOKEN" > ~/.rbkRscsession.$id_string + +} + +rsc_api_get () { + check_get_rsc_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $RSC_AUTH_TOKEN") + check_http_error +} + +rsc_api_post () { + check_get_rsc_token + http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $RSC_AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD) + check_http_error +} + +rsc_gql_query_old () { + + check_get_rsc_token + + ENDPOINT="https://${RSC_HOST}/api/graphql" + + #curl -s -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT \ + curl -s -o /tmp/rbkresponse.$$ -X POST $ENDPOINT \ + -H "Authorization: Bearer ${RSC_AUTH_TOKEN}" \ + -H 'Content-Type: application/json' \ + -d @- < /tmp/payload.$$ + {"query": "$gqlQuery", "variables": $gqlVars} +EOF + + http_response=$(curl -s -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT \ + -H "Authorization: Bearer ${RSC_AUTH_TOKEN}" \ + -H 'Content-Type: application/json' \ + -d @/tmp/payload.$$) + + #cat /tmp/payload.$$ | jq -r + error=$(cat /tmp/rbkresponse.$$ | jq -r '.errors // empty') + if [ "$error" ]; then + echo "ERROR: The last GraphQL API call returned an error" + echo + echo "PAYLOAD:" + cat /tmp/payload.$$ | jq -r + echo "RESPONSE:" + cat /tmp/rbkresponse.$$ | jq -r '.errors' + exit_with_error + fi + + check_http_error + +} + +rsc_find_database () { + + # if cluster_uuid is not set, get it + # gql query to find DB name, return the best one (based on CDM UUID etc) + # + + if [ -z "${cluster_uuid}" ]; then + #echo cluster UUID not, set, getting it + get_cluster_uuid + #echo Cluster UUID is $cluster_uuid + else + echo Cluster UUID was already $cluster_uuid + fi + + variables="{ + \"filter\":[{\"field\":\"REGEX\",\"texts\":[\"$RBK_SID\"]},{\"field\":\"IS_GHOST\",\"texts\":[\"false\"]},{\"field\":\"IS_ACTIVE\",\"texts\":[\"true\"]},{\"field\":\"CLUSTER_ID\",\"texts\":[\"$cluster_uuid\"]}], + \"sortBy\":\"NAME\", + \"sortOrder\":\"ASC\", + \"first\":500 + }" + + gql_GlobalSearchOracle='query GlobalSearchObjectQuery($first: Int!, $filter: [Filter!]!, $sortBy: HierarchySortByField, $sortOrder: SortOrder, $after: String) { + globalSearchResults( + first: $first + filter: $filter + sortBy: $sortBy + sortOrder: $sortOrder + after: $after + ) { + edges { + cursor + node { + id + name + objectType + logicalPath { + fid + name + objectType + __typename + } + physicalPath { + fid + name + objectType + __typename + } + ... on HierarchyObject { + ...EffectiveSlaColumnFragment + __typename + } + ... on OracleDatabase { + cluster { + ...ClusterFragment + __typename + } + primaryClusterLocation { + id + __typename + } + isRelic + __typename + } + ... on OracleRac { + cluster { + ...ClusterFragment + __typename + } + primaryClusterLocation { + id + __typename + } + __typename + } + ... on OracleDataGuardGroup { + cluster { + ...ClusterFragment + __typename + } + primaryClusterLocation { + id + __typename + } + isRelic + __typename + } + __typename + } + __typename + } + pageInfo { + endCursor + startCursor + hasNextPage + hasPreviousPage + __typename + } + __typename + } +} + +fragment ClusterFragment on Cluster { + id + name + __typename +} + +fragment EffectiveSlaColumnFragment on HierarchyObject { + id + effectiveSlaDomain { + ...EffectiveSlaDomainFragment + ... on GlobalSlaReply { + description + __typename + } + __typename + } + ... on CdmHierarchyObject { + pendingSla { + ...SLADomainFragment + __typename + } + __typename + } + __typename +} + +fragment EffectiveSlaDomainFragment on SlaDomain { + id + name + ... on GlobalSlaReply { + isRetentionLockedSla + retentionLockMode + __typename + } + ... on ClusterSlaDomain { + fid + cluster { + id + name + __typename + } + isRetentionLockedSla + retentionLockMode + __typename + } + __typename +} + +fragment SLADomainFragment on SlaDomain { + id + name + ... on ClusterSlaDomain { + fid + cluster { + id + name + __typename + } + __typename + } + __typename +}' + +gqlQuery="$(echo $gql_GlobalSearchOracle)" +gqlVars="$(echo $variables)" +rsc_gql_query + +#cat /tmp/rbkresponse.$$ | jq -r + +num=$(cat /tmp/rbkresponse.$$ | jq -r '[.data.globalSearchResults.edges[] | select (.node.objectType=="ORACLE_DATA_GUARD_GROUP" and .node.isRelic==false)]| length') + +if [ $num -eq 1 ]; then + #echo Good, There is just one DG with name $RBK_SID + read name rsc_db_id < <(echo $(cat /tmp/rbkresponse.$$ | jq -r '.data.globalSearchResults.edges[] | select (.node.objectType=="ORACLE_DATA_GUARD_GROUP" and .node.isRelic==false)| .node.name, .node.id')) + database_type="Data Guard" +elif [ $num -gt 1 ]; then + echo "ERROR: There were $num entries returned for Data Guard databases with name $RBK_SID" + exit_with_error +fi + +if [ -z "$rsc_db_id" ]; then + #echo INFO: No Data Guard DB found with SID $RBK_SID. Looking for standalone DBs + + if [ -z "$RBK_HOST" ]; then + num=$(cat /tmp/rbkresponse.$$ | jq -r '[.data.globalSearchResults.edges[] | select (.node.objectType=="OracleDatabase" and .node.isRelic==false)] | length') + if [ $num -eq 1 ]; then + read name rsc_db_id < <(echo $(cat /tmp/rbkresponse.$$ | jq -r '.data.globalSearchResults.edges[] | select (.node.objectType=="OracleDatabase" and .node.isRelic==false)| .node.name, .node.id')) + database_type="Standalone" + #echo Good, There is just one Standalone DB with name $name and RSC ID $rsc_db_id + else + echo "ERROR: There were $num entries returned from JQ for DB with name $RBK_SID on host $RBK_HOST" + exit_with_error + fi + else + num=$(cat /tmp/rbkresponse.$$ | jq -r --arg HOST "$RBK_HOST" '[.data.globalSearchResults.edges[] | select (.node.logicalPath[0].name==$HOST and .node.objectType=="OracleDatabase" and .node.isRelic==false)] | length') + if [ $num -eq 1 ]; then + read name rsc_db_id < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg HOST "$RBK_HOST" '.data.globalSearchResults.edges[] | select (.node.logicalPath[0].name==$HOST and .node.objectType=="OracleDatabase" and .node.isRelic==false)| .node.name, .node.id')) + database_type="Standalone" + #echo Good, There is just one Standalone DB with name $name on ${RBK_HOST} and RSC ID $rsc_db_id + else + echo "ERROR: There were $num entries returned from for DB with name $RBK_SID on host $RBK_HOST" + exit_with_error + fi + fi +fi +} + diff --git a/rbk_api.conf b/rbk_api.conf new file mode 100644 index 0000000..8e04b10 --- /dev/null +++ b/rbk_api.conf @@ -0,0 +1,12 @@ +# IP Address (or DNS name) of Rubrik CDM +##RUBRIK_IP=rubrik-p2.mobi.mobicorp.ch +RUBRIK_IP=jp-edge-proxmox.pattinson.org + +#AUTH_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0NjlmMGUzNS00OWQxLTQ2NTEtOGY1ZS00MjA5OTU0MTU3NmUiLCJpc01mYVJlbWVtYmVyVG9rZW4iOmZhbHNlLCJpc3MiOiJmZWU2MDYzNy05Y2Q4LTRjMmItOTM4NS1hNjljMjViNTA0YmUiLCJpc1JlZHVjZWRTY29wZSI6ZmFsc2UsImlhdCI6MTY3NDYzNjAzNiwianRpIjoiZGQ5MjhmYzQtODM3Mi00ZWE4LWIzMDQtNzg4MjY4MDNkYjc3In0.2-ZQQvm0TmmujVQxJEEB8w8xjhowx5GjBfdBeDkiPVw + +ID="client|673af632-150d-47e0-908e-66a6d71fe621" +SECRET=lIHYPGMjmDLf3jflRRHtl1Oqf0YlfY7z0YNdwLG0VetfKuiVkIl_SsD4QAjAhEOb + +RSC_HOST=rubrik-rbkpso20.my.rubrik.com +#RSC_ID="client|d332d008-a86b-4943-b5c4-b3d9720b1960" +#RSC_SECRET=