#!/usr/bin/ksh # # Oracle shell script support functions # Written for HCL / Nokia # v1.0 - James Pattinson - October 2025 nowait=0 LOGFILE=$API_LOG_DIR/api_calls.log mkdir -p $API_LOG_DIR tabwidth=25 # Portable short hostname function get_short_hostname() { if hostname -s >/dev/null 2>&1; then hostname -s else hostname | awk -F. '{print $1}' fi } HOST=$(get_short_hostname) # Detect OS and set DATE variable appropriately os_name=$(uname -s) case "$os_name" in Linux) DATE=$(which date) ;; SunOS) # Solaris DATE=/usr/gnu/bin/date ;; HP-UX) # HP/UX: try gdate, fallback to date with warning if command -v gdate >/dev/null 2>&1; then DATE=$(command -v gdate) else DATE=$(command -v date) echo "WARNING: GNU date (gdate) not found. Date arithmetic may not work on HP/UX." >&2 fi ;; *) DATE=$(which date) ;; esac echo "`$DATE` -$$-: CALLED $0 $@" >> $LOGFILE trap ctrl_c INT ctrl_c() { echo "`$DATE` -$$-: TRAPPED CTRL-C - EXITING" >> $LOGFILE exit_with_error } ctrl_c_inhibit() { echo "`$DATE` -$$-: TRAPPED CTRL-C - CONTINUING" >> $LOGFILE } exit_with_error() { ENDPOINT="https://$RUBRIK_IP/api/v1/session/me" rest_api_delete check_http_error cat /tmp/rbkresponse.$$ | mailx -s "Backup error on ${HOST} for ${ORACLE_SID}. Please investigate" $ALERT_EMAILS rm -f /tmp/rbkresponse.$$ rm -f /tmp/mountedDBs.$$ rm -f $PIDFILE echo Aborting Script! echo "`$DATE` -$$-: EXITED WITH ERROR $0 $@" >> $LOGFILE 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 } check_pid() { if [ -f $PIDFILE ] then PID=$(cat $PIDFILE) if ps -p $PID > /dev/null 2>&1; then echo "ERROR: MV already being used by process ID $PID" if ps -fp $PID > /dev/null 2>&1; then ps -fp $PID else ps -ef | awk -v pid=$PID '$2==pid' fi exit_with_error else ## Process not found assume not running echo $$ > $PIDFILE if [ $? -ne 0 ] then echo "ERROR: Could not create mvLock file" exit_with_error fi fi else echo $$ > $PIDFILE if [ $? -ne 0 ] then echo "ERROR: Could not create mvLock file" exit_with_error fi fi } # Get a new token only if AUTH_TOKEN is not already set check_get_token() { if [ -z "$AUTH_TOKEN" ]; then get_token fi } get_token() { echo "`$DATE` -$$-: AUTH USER $ID" >> $LOGFILE 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.$$ | awk '{match($0, /"token":"[^"]*"/); if (RSTART > 0) {print substr($0, RSTART+9, RLENGTH-10);}}') echo "`$DATE` -$$-: AUTH SESSION $SESSION" >> $LOGFILE } # 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") echo "`$DATE` -$$-: REST API GET: ENDPOINT $ENDPOINT" >> $LOGFILE echo "`$DATE` -$$-: REST API GET: RESPONSE STARTS" >> $LOGFILE cat /tmp/rbkresponse.$$ >> $LOGFILE echo >> $LOGFILE echo "`$DATE` -$$-: REST API GET: RESPONSE ENDS" >> $LOGFILE check_http_error } rest_api_get_2() { check_get_token http_response=$(curl -s -k -o /tmp/rbkresponse2.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN") echo "`$DATE` -$$-: REST API GET: ENDPOINT $ENDPOINT" >> $LOGFILE echo "`$DATE` -$$-: REST API GET: RESPONSE STARTS" >> $LOGFILE cat /tmp/rbkresponse2.$$ >> $LOGFILE echo >> $LOGFILE echo "`$DATE` -$$-: REST API GET: RESPONSE ENDS" >> $LOGFILE 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) echo "`$DATE` -$$-: REST API POST: ENDPOINT $ENDPOINT" >> $LOGFILE echo "`$DATE` -$$-: REST API POST: PAYLOAD $PAYLOAD" >> $LOGFILE echo "`$DATE` -$$-: REST API POST: RESPONSE STARTS" >> $LOGFILE cat /tmp/rbkresponse.$$ >> $LOGFILE echo >> $LOGFILE echo "`$DATE` -$$-: REST API POST: RESPONSE ENDS" >> $LOGFILE 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") echo "`$DATE` -$$-: REST API POST: ENDPOINT $ENDPOINT" >> $LOGFILE echo "`$DATE` -$$-: REST API POST: PAYLOAD " >> $LOGFILE echo "`$DATE` -$$-: REST API POST: RESPONSE STARTS" >> $LOGFILE cat /tmp/rbkresponse.$$ >> $LOGFILE echo >> $LOGFILE echo "`$DATE` -$$-: REST API POST: RESPONSE ENDS" >> $LOGFILE 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") echo "`$DATE` -$$-: REST API PATCH: ENDPOINT $ENDPOINT" >> $LOGFILE echo "`$DATE` -$$-: REST API PATCH: PAYLOAD $PAYLOAD" >> $LOGFILE echo "`$DATE` -$$-: REST API PATCH: RESPONSE STARTS" >> $LOGFILE cat /tmp/rbkresponse.$$ >> $LOGFILE echo >> $LOGFILE echo "`$DATE` -$$-: REST API PATCH: RESPONSE ENDS" >> $LOGFILE 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") echo "`$DATE` -$$-: REST API DELETE: $http_response: ENDPOINT $ENDPOINT" >> $LOGFILE check_http_error } get_mv() { ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false" rest_api_get mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$) numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/rbkresponse.$$) if [[ $mvId == "" ]]; then echo ERROR: MV with name $mv_name was not found exit_with_error fi } get_data_mv() { mv_name=${HOST}_${ORACLE_SID}_data ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false" rest_api_get mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$) numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/rbkresponse.$$) if [[ $mvId == "" ]]; then echo ERROR: MV with name $mv_name was not found exit_with_error fi } get_log_mv() { # Look for a log volume. If not present, return the data volume mv_name=${HOST}_${ORACLE_SID}_logs ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false" rest_api_get logMvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$) if [[ $logMvId == "" ]]; then echo "INFO: Log volume ($mv_name) not found. Logs will be written to DB volume" logMvPresent=0 mv_name=${HOST}_${ORACLE_SID}_data ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false" rest_api_get mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$) numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/rbkresponse.$$) if [[ $mvId == "" ]]; then echo ERROR: MV with name $mv_name was not found exit_with_error fi else mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$) numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/rbkresponse.$$) logMvPresent=1 echo "INFO: Log volume ($mv_name) exists with $numChannels channels" fi } open_mv() { PIDFILE=/tmp/mvLock_${mv_name}.pid check_pid ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume/$mvId/begin_snapshot" echo "Opening MV $mv_name with ID $mvId (numChannels is $numChannels)" rest_api_post_empty } close_mv() { if [ -z "${SLANAME}" ]; then echo Closing MV $mv_name using default assigned SLA ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume/$mvId/end_snapshot" rest_api_post_empty else get_sla echo Closing MV $mv_name as On Demand with SLA $SLANAME ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume/$mvId/end_snapshot" PAYLOAD="{\"retentionConfig\":{\"slaId\":\"$slaId\"}}" rest_api_post fi } cleanup() { ENDPOINT="https://$RUBRIK_IP/api/v1/session/me" rest_api_delete echo "`$DATE` -$$-: EXITED $0 $@" >> $LOGFILE rm -f /tmp/rbkresponse.$$ rm -f $PIDFILE }