checkpoint
This commit is contained in:
91
check_recoverable_range.sh
Executable file
91
check_recoverable_range.sh
Executable file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Fetch recoverable ranges for a given Oracle DB
|
||||||
|
# v0.2 - James Pattinson - August 2021
|
||||||
|
#
|
||||||
|
# usage: oracle_get_rr.sh [-h <dbhost>] <SID>
|
||||||
|
|
||||||
|
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 <dbhost>] [-g] <SID>" 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
|
||||||
|
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"
|
||||||
|
# rest_api_get
|
||||||
|
# echo "http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w \"%{http_code}\" -X GET $ENDPOINT -H \"accept: application/json\" -H \"Authorization: Bearer $AUTH_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 "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
|
||||||
131
oracle_clone.sh
Executable file
131
oracle_clone.sh
Executable file
@@ -0,0 +1,131 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Perform a Live Mount of an Oracle DB
|
||||||
|
# v0.2 - James Pattinson - August 2021
|
||||||
|
#
|
||||||
|
# usage: oracle_mount.sh [-h <dbhost>] [-d <oracle_home> [-f] [-t <timestamp>] <srcSID> <tgtHOSTNAME>
|
||||||
|
#
|
||||||
|
# -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
|
||||||
|
|
||||||
|
MYDIR="$(dirname "$(realpath "$0")")"
|
||||||
|
# source $MYDIR/rbk_api.conf
|
||||||
|
source $MYDIR/oracle_funcs.sh
|
||||||
|
|
||||||
|
usage() { echo "Usage: $0 [-h <dbhost>] [-d <oracle_home> [-f|-n] <srcSID> <tgtHOSTNAME> <\"timestamp\">" 1>&2
|
||||||
|
echo "Format Timestamp YYYY-MM-DD HH:MM:SS"
|
||||||
|
exit 1; }
|
||||||
|
|
||||||
|
filesonly=false
|
||||||
|
|
||||||
|
while getopts "h:d:t:f" o; do
|
||||||
|
case "${o}" in
|
||||||
|
h)
|
||||||
|
RBK_HOST=${OPTARG}
|
||||||
|
;;
|
||||||
|
f)
|
||||||
|
filesonly=true
|
||||||
|
;;
|
||||||
|
d)
|
||||||
|
oraclehome=${OPTARG}
|
||||||
|
;;
|
||||||
|
t)
|
||||||
|
datestring=${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'
|
||||||
|
exit_with_error
|
||||||
|
fi
|
||||||
|
|
||||||
|
target_id=$(cat /tmp/rbkresponse.$$ | jq -r '.data[0].id')
|
||||||
|
|
||||||
|
# convert datestamp from string into milliseconds
|
||||||
|
if [ -z "$datestring" ]; then
|
||||||
|
echo "No timestamp specified, determining latest recoverable"
|
||||||
|
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/recoverable_range"
|
||||||
|
rest_api_get
|
||||||
|
datestring=$(cat /tmp/rbkresponse.$$ | jq -r '[.data[].endTime] | max')
|
||||||
|
fi
|
||||||
|
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))
|
||||||
|
|
||||||
|
exit
|
||||||
|
|
||||||
|
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[]'
|
||||||
|
RBK_ID_LV=$(cat /tmp/rbkresponse.$$ | jq -r '.data[] | select(.status=="Mounting") | .id')
|
||||||
|
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
|
||||||
307
oracle_funcs.sh
Normal file → Executable file
307
oracle_funcs.sh
Normal file → Executable file
@@ -1,44 +1,53 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
|
#--------------------------------------------------------------------------------------------------------
|
||||||
# Oracle shell script support functions
|
# Oracle shell script support functions
|
||||||
# v0.2 - James Pattinson - March 2022
|
# 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
|
||||||
|
|
||||||
|
# -- 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
|
nowait=0
|
||||||
|
|
||||||
LOGFILE=/tmp/rubrik_oracle.log
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
tabwidth=25
|
DATE=gdate
|
||||||
|
|
||||||
os=$(uname -o)
|
|
||||||
if [ $os == "Solaris" ]; then
|
|
||||||
# Use the GNU version of date binary
|
|
||||||
DATE=/usr/gnu/bin/date
|
|
||||||
else
|
else
|
||||||
DATE=$(which date)
|
DATE=date
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "`$DATE` -$$-: CALLED $0 $@" >> $LOGFILE
|
|
||||||
|
|
||||||
trap ctrl_c INT
|
|
||||||
|
|
||||||
function ctrl_c () {
|
|
||||||
echo "`$DATE` -$$-: TRAPPED CTRL-C - EXITING" >> $LOGFILE
|
|
||||||
exit_with_error
|
|
||||||
}
|
|
||||||
|
|
||||||
function ctrl_c_inhibit () {
|
|
||||||
echo "`$DATE` -$$-: TRAPPED CTRL-C - CONTINUING" >> $LOGFILE
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_with_error () {
|
exit_with_error () {
|
||||||
# if [ $usingsatoken ]; then
|
|
||||||
# ENDPOINT="https://$RUBRIK_IP/api/v1/session/me"
|
|
||||||
# rest_api_delete
|
|
||||||
# check_http_error
|
|
||||||
# fi
|
|
||||||
rm -f /tmp/rbkresponse.$$
|
rm -f /tmp/rbkresponse.$$
|
||||||
rm -f /tmp/mountedDBs.$$
|
|
||||||
echo Aborting Script!
|
echo Aborting Script!
|
||||||
echo "`$DATE` -$$-: EXITED WITH ERROR $0 $@" >> $LOGFILE
|
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
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,85 +59,9 @@ check_http_error () {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_db () {
|
|
||||||
|
|
||||||
read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name rac_name last_snap isrelic < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg ID "OracleDatabase:::$id" '.data[] | select(.id==$ID) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName, .racName, .lastSnapshotTime, .isRelic'))
|
|
||||||
if [ "$dg_id" != "null" ]; then
|
|
||||||
if [ "$last_snap" != "null" ]; then
|
|
||||||
[[ $rac_name != "null" ]] && string=$rac_name || string=$RBK_HOST
|
|
||||||
echo "WARNING: DG member on $string has snapshots created when DB was protected as standalone (non DG)"
|
|
||||||
echo "WARNING: Latest standalone snapshot taken $last_snap. Use -h $string to view or utilise them"
|
|
||||||
fi
|
|
||||||
id=$(echo $dg_id | cut -d: -f 4)
|
|
||||||
if [[ ! " ${DGDBs[*]} " =~ " ${id} " ]]; then
|
|
||||||
DGDBs+=("$id")
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
actualDBs+=("$id")
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
show_all_dbs () {
|
|
||||||
|
|
||||||
liveDBs=()
|
|
||||||
liveDBsWithSnaps=()
|
|
||||||
|
|
||||||
for id in "${actualDBs[@]}"; do
|
|
||||||
# cat /tmp/rbkresponse.$$ | jq -r
|
|
||||||
read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name rac_name isrelic standaloneHostName last_snap db_unique_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, .racName, .isRelic, .standaloneHostName, .lastSnapshotTime, .dbUniqueName'))
|
|
||||||
echo -n "WARNING: Object ID $id on "
|
|
||||||
[[ $standaloneHostName != "null" ]] && echo -n "host $standaloneHostName "
|
|
||||||
[[ $rac_name != "null" ]] && echo -n "RAC $rac_name "
|
|
||||||
[[ $grp_name != "null" ]] && echo "DG ID: $grp_name"
|
|
||||||
[[ $isrelic = "true" ]] && echo -n "(Relic)" || liveDBs+=("$id")
|
|
||||||
[[ $last_snap != "null" ]] && [[ $isrelic = "false" ]] && liveDBsWithSnaps+=("$id")
|
|
||||||
echo
|
|
||||||
done
|
|
||||||
|
|
||||||
#declare -p liveDBs
|
|
||||||
#declare -p liveDBsWithSnaps
|
|
||||||
|
|
||||||
for id in "${DGDBs[@]}"; do
|
|
||||||
echo -n "WARNING: Object ID $id on DG Group "
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/OracleDatabase:::$id"
|
|
||||||
rest_api_get_2
|
|
||||||
dgname=$(cat /tmp/rbkresponse2.$$ | jq -r '.dbUniqueName')
|
|
||||||
rm -f /tmp/rbkresponse2.$$
|
|
||||||
echo $dgname
|
|
||||||
done
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
select_db () {
|
|
||||||
|
|
||||||
# We have more than one matching DB. Select the best one
|
|
||||||
if [ "${#DGDBs[@]}" -eq 1 ]; then
|
|
||||||
echo WARNING: Selecting Data Guard DB ${DGDBs[0]}
|
|
||||||
id="${DGDBs[0]}"
|
|
||||||
elif [ "${#liveDBs[@]}" -eq 1 ]; then
|
|
||||||
echo WARNING: Selecting object ID ${liveDBs[0]} as it is not a Relic
|
|
||||||
id="${liveDBs[0]}"
|
|
||||||
elif [ "${#liveDBsWithSnaps[@]}" -eq 1 ]; then
|
|
||||||
echo WARNING: Selecting object ID ${liveDBsWithSnaps[0]} as it is not a Relic and has snapshots
|
|
||||||
id="${liveDBsWithSnaps[0]}"
|
|
||||||
else
|
|
||||||
echo "ERROR: Unable to determine unique DB. Please specify one of the above"
|
|
||||||
exit_with_error
|
|
||||||
fi
|
|
||||||
|
|
||||||
read name db_id sla_id dg_type dg_id RBK_HOST num_instances grp_name rac_name isrelic standaloneHostName last_snap < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg ID "OracleDatabase:::$id" '.data[] | select(.id==$ID or .dataGuardGroupId==$ID) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .instances[0].hostName, .numInstances, .dataGuardGroupName, .racName, .isRelic, .standaloneHostName, .lastSnapshotTime'))
|
|
||||||
|
|
||||||
#exit_with_error
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Given RBK_SID return $db_id of matching database
|
# Given RBK_SID return $db_id of matching database
|
||||||
find_database () {
|
find_database () {
|
||||||
|
|
||||||
specifiedhost=$RBK_HOST
|
|
||||||
|
|
||||||
# First get IDs of all the mounted DBs for this SID
|
# First get IDs of all the mounted DBs for this SID
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount"
|
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount"
|
||||||
rest_api_get
|
rest_api_get
|
||||||
@@ -139,14 +72,26 @@ find_database () {
|
|||||||
ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?name=$RBK_SID"
|
ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db?name=$RBK_SID"
|
||||||
rest_api_get
|
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 no host is specified then just look for the DB with the right SID
|
||||||
if [ -z $RBK_HOST ]; then
|
if [ -z $RBK_HOST ]; then
|
||||||
|
|
||||||
# get list of DB IDs in scope (sid matches and not a relic)
|
# 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) | .id' | sort | uniq)
|
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)
|
||||||
myDGs=$(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID) | .dataGuardGroupId' | sort | uniq)
|
|
||||||
|
|
||||||
for db in $myDBs $myDGs; do
|
for db in $myDBs; do
|
||||||
id=$(echo $db | cut -d: -f 4)
|
id=$(echo $db | cut -d: -f 4)
|
||||||
if grep -q $id /tmp/mountedDBs.$$; then
|
if grep -q $id /tmp/mountedDBs.$$; then
|
||||||
continue
|
continue
|
||||||
@@ -155,36 +100,15 @@ find_database () {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
myDBs=( $(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID) | .id' | sort | uniq) )
|
# Get the details for the specific DB ID
|
||||||
myDGs=( $(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" '.data[] | select(.name==$SID) | .dataGuardGroupId' | sort | uniq) )
|
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'))
|
||||||
actualDBs=()
|
|
||||||
DGDBs=()
|
|
||||||
|
|
||||||
for db in "${myDBs[@]}"; do
|
|
||||||
id=$(echo $db | cut -d: -f 4)
|
|
||||||
resolve_db
|
|
||||||
done
|
|
||||||
if [ "$(( ${#actualDBs[@]} + ${#DGDBs[@]} ))" -gt 1 ]; then
|
|
||||||
echo "WARNING: There are multiple instances of $RBK_SID. Please re run the script with the -h option"
|
|
||||||
echo "WARNING: to interact with them. Script will attempt to select the correct DB."
|
|
||||||
show_all_dbs
|
|
||||||
select_db
|
|
||||||
else
|
|
||||||
id="${actualDBs[0]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
else
|
|
||||||
# Host was specified
|
# Host was specified
|
||||||
hostspecified=true
|
else
|
||||||
read name db_id sla_id dg_type dg_id RBK_HOST racname num_instances grp_name < <(echo $(cat /tmp/rbkresponse.$$ | jq -r --arg SID "$RBK_SID" --arg HOST "$RBK_HOST" '.data[] | select(.name==$SID and (.infraPath[0].name==$HOST or .dataGuardGroupName==$HOST)) | .name, .id, .effectiveSlaDomainId, .dataGuardType, .dataGuardGroupId, .standaloneHostName, .racName, .numInstances, .dataGuardGroupName'))
|
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
|
fi
|
||||||
|
|
||||||
if [ "$RBK_HOST" = "null" ] && [ "$racname" != "null" ]; then
|
if [ "$dg_type" == "DataGuardMember" ]; then
|
||||||
RBK_HOST=$racname
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$dg_type" == "DataGuardMember" ] && [ "$hostspecified" != "true" ] || [[ "$specifiedhost" == DG_GROUP* ]]; then
|
|
||||||
db_id=$dg_id
|
db_id=$dg_id
|
||||||
# Now find SLA of the DG GROUP not just the DB (which will be unprotected)
|
# 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"
|
ENDPOINT="https://$RUBRIK_IP/api/v1/oracle/db/$db_id"
|
||||||
@@ -193,44 +117,34 @@ find_database () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$db_id" ]; then
|
if [ -z "$db_id" ]; then
|
||||||
locate_mv_db
|
echo FATAL: No DB found with SID $RBK_SID on host $RBK_HOST
|
||||||
fi
|
if [ "${SCRIPT}" = "check_recoverable_range.sh" ] ; then
|
||||||
|
export ret=11
|
||||||
if [ -z "$db_id" ]; then
|
else
|
||||||
echo FATAL: No DB found with SID $RBK_SID on host / cluster $RBK_HOST
|
|
||||||
exit_with_error
|
exit_with_error
|
||||||
fi
|
fi
|
||||||
}
|
else
|
||||||
|
echo " db_id is: $db_id"
|
||||||
locate_mv_db () {
|
|
||||||
|
|
||||||
# Look for a pair of MVs with names like $RBK_SID_data and $RBK_SID_logs
|
|
||||||
|
|
||||||
# Get list of MVs
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume"
|
|
||||||
rest_api_get
|
|
||||||
|
|
||||||
mvData=$(cat /tmp/rbkresponse.$$ | jq -r --arg NAME ${RBK_SID}_data '.data[] | select(.name==$NAME)| .id')
|
|
||||||
mvLogs=$(cat /tmp/rbkresponse.$$ | jq -r --arg NAME ${RBK_SID}_logs '.data[] | select(.name==$NAME)| .id')
|
|
||||||
|
|
||||||
if [ -n "$mvData" ] && [ -n "$mvLogs" ]; then
|
|
||||||
echo "INFO: MV found (Solaris Database)"
|
|
||||||
db_id=ManagedVolume
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_get_token () {
|
check_get_token () {
|
||||||
|
|
||||||
if [ -z "${AUTH_TOKEN}" ]; then
|
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)
|
id_string=$(echo $ID | cut -d: -f 4)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If there is a cached credential file, use it
|
||||||
if [ -f ~/.rbksession.$id_string ]; then
|
if [ -f ~/.rbksession.$id_string ]; then
|
||||||
echo "`$DATE` -$$-: AUTH SESSION FILE EXISTS" >> $LOGFILE
|
|
||||||
read expiration token < <(echo $(cat ~/.rbksession.$id_string))
|
read expiration token < <(echo $(cat ~/.rbksession.$id_string))
|
||||||
if [ $($DATE +%s -d $expiration) -lt $(( $($DATE +%s) + 7200 )) ]; then
|
# If token expires within 30 min, get a new one
|
||||||
echo "`$DATE` -$$-: AUTH TOKEN EXPIRED" >> $LOGFILE
|
if [ $($DATE +%s -d $expiration) -lt $(( $($DATE +%s) + 1800 )) ]; then
|
||||||
get_token
|
get_token
|
||||||
else
|
else
|
||||||
AUTH_TOKEN=$token
|
AUTH_TOKEN=$token
|
||||||
@@ -243,8 +157,6 @@ check_get_token () {
|
|||||||
|
|
||||||
get_token () {
|
get_token () {
|
||||||
|
|
||||||
trap '' INT
|
|
||||||
echo "`$DATE` -$$-: AUTH USER $ID" >> $LOGFILE
|
|
||||||
MYENDPOINT="https://$RUBRIK_IP/api/v1/service_account/session"
|
MYENDPOINT="https://$RUBRIK_IP/api/v1/service_account/session"
|
||||||
MYPAYLOAD="{\"serviceAccountId\":\"$ID\",\"secret\":\"$SECRET\"}"
|
MYPAYLOAD="{\"serviceAccountId\":\"$ID\",\"secret\":\"$SECRET\"}"
|
||||||
|
|
||||||
@@ -254,33 +166,14 @@ get_token () {
|
|||||||
AUTH_TOKEN=$(cat /tmp/rbkresponse.$$ | jq -r '.token')
|
AUTH_TOKEN=$(cat /tmp/rbkresponse.$$ | jq -r '.token')
|
||||||
SESSION=$(cat /tmp/rbkresponse.$$ | jq -r '.sessionId')
|
SESSION=$(cat /tmp/rbkresponse.$$ | jq -r '.sessionId')
|
||||||
EXPIRATION=$(cat /tmp/rbkresponse.$$ | jq -r '.expirationTime')
|
EXPIRATION=$(cat /tmp/rbkresponse.$$ | jq -r '.expirationTime')
|
||||||
echo "`$DATE` -$$-: AUTH SESSION $SESSION" >> $LOGFILE
|
|
||||||
echo "`$DATE` -$$-: SAVING TOKEN TO FILE" >> $LOGFILE
|
|
||||||
echo "$EXPIRATION $AUTH_TOKEN" > ~/.rbksession.$id_string
|
echo "$EXPIRATION $AUTH_TOKEN" > ~/.rbksession.$id_string
|
||||||
usingsatoken=1
|
|
||||||
trap ctrl_c INT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTTP GET: Given $ENDPOINT write output to file
|
# HTTP GET: Given $ENDPOINT write output to file
|
||||||
rest_api_get () {
|
rest_api_get () {
|
||||||
check_get_token
|
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")
|
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
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,46 +181,33 @@ rest_api_get_2 () {
|
|||||||
rest_api_post () {
|
rest_api_post () {
|
||||||
check_get_token
|
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)
|
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
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
rest_api_post_empty () {
|
rest_api_post_empty () {
|
||||||
check_get_token
|
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")
|
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 <NULL>" >> $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
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
rest_api_patch () {
|
rest_api_patch () {
|
||||||
check_get_token
|
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")
|
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
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
rest_api_delete () {
|
rest_api_delete () {
|
||||||
check_get_token
|
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")
|
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
|
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
|
# Given an ENDPOINT of an async job, monitor it
|
||||||
check_status () {
|
check_status () {
|
||||||
if [ $nowait -ne 1 ]; then
|
if [ $nowait -ne 1 ]; then
|
||||||
@@ -335,34 +215,33 @@ check_status () {
|
|||||||
while true; do
|
while true; do
|
||||||
rest_api_get
|
rest_api_get
|
||||||
status=$(cat /tmp/rbkresponse.$$ | jq -r '.status')
|
status=$(cat /tmp/rbkresponse.$$ | jq -r '.status')
|
||||||
if [ $status != "SUCCEEDED" ] && [ $status != "FAILED" ]; then
|
if [ $status != "SUCCEEDED" ] && [ $status != "FAILED" ] && [ $status != "CANCELED" ] && [ $status != "UNDOING" ]; then
|
||||||
echo Status is $status, checking in 30 seconds
|
echo Status is $status, checking in 30 seconds
|
||||||
else
|
else
|
||||||
if [ $status != "SUCCEEDED" ]; then
|
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
|
echo OPERATION FAILED WITH STATUS $status
|
||||||
exit_with_error
|
exit_with_error
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo OPERATION SUCCEEDED
|
echo OPERATION SUCCEEDED
|
||||||
return
|
exit 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
sleep 30
|
sleep 30
|
||||||
done
|
done
|
||||||
else
|
|
||||||
# Show the Job ID
|
|
||||||
JOB_ID=$(cat /tmp/rbkresponse.$$ | jq -r '.id')
|
|
||||||
echo "Job submittsed. For more details of the job run:"
|
|
||||||
echo "oracle_jobs.sh -d $RBK_SID -j $JOB_ID"
|
|
||||||
echo "RMAN logs, if applioable, will be in /var/log/rubrik/script_logs/"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup () {
|
cleanup () {
|
||||||
# if [ $usingsatoken ]; then
|
|
||||||
# ENDPOINT="https://$RUBRIK_IP/api/v1/session/me"
|
|
||||||
# rest_api_delete
|
|
||||||
# fi
|
|
||||||
echo "`$DATE` -$$-: EXITED $0 $@" >> $LOGFILE
|
|
||||||
rm -f /tmp/mountedDBs.$$
|
rm -f /tmp/mountedDBs.$$
|
||||||
rm -f /tmp/rbkresponse.$$
|
rm -f /tmp/rbkresponse.$$
|
||||||
|
rm -f /tmp/payload.$$
|
||||||
}
|
}
|
||||||
|
|||||||
33
oracle_list_db.sh
Executable file
33
oracle_list_db.sh
Executable file
@@ -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 <HOSTNAME>
|
||||||
|
|
||||||
|
MYDIR="$(dirname "$(realpath "$0")")"
|
||||||
|
# source $MYDIR/rbk_api.conf
|
||||||
|
source $MYDIR/oracle_funcs.sh
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <dbhost>"
|
||||||
|
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
|
||||||
253
oracle_mount.sh
Normal file → Executable file
253
oracle_mount.sh
Normal file → Executable file
@@ -6,54 +6,32 @@
|
|||||||
# usage: oracle_mount.sh [-h <dbhost>] [-d <oracle_home> [-f] <srcSID> <tgtHOSTNAME> <"timestamp">
|
# usage: oracle_mount.sh [-h <dbhost>] [-d <oracle_home> [-f] <srcSID> <tgtHOSTNAME> <"timestamp">
|
||||||
#
|
#
|
||||||
# -d specify $ORACLE_HOME on target - needed for mount of Data Guard DBs
|
# -d specify $ORACLE_HOME on target - needed for mount of Data Guard DBs
|
||||||
# default is to performing a files-only mount
|
# -f mount files only - do not create database
|
||||||
# -l mount and create DB Live Mount
|
|
||||||
#
|
#
|
||||||
# Timestamp YYYY-MM-DD HH:MM:SS
|
# Timestamp YYYY-MM-DD HH:MM:SS
|
||||||
# Time is passed to 'date' on THIS machine, will use local timezone
|
# Time is passed to 'date' on THIS machine, will use local timezone
|
||||||
|
|
||||||
MYDIR="$(dirname "$(realpath "$0")")"
|
MYDIR="$(dirname "$(realpath "$0")")"
|
||||||
source $MYDIR/rbk_api.conf
|
# source $MYDIR/rbk_api.conf
|
||||||
source $MYDIR/oracle_funcs.sh
|
source $MYDIR/oracle_funcs.sh
|
||||||
|
|
||||||
# Local commands to mount and unmount NFS volumes
|
usage() { echo "Usage: $0 [-h <dbhost>] [-d <oracle_home> [-f|-n] <srcSID> <tgtHOSTNAME> <\"timestamp\">" 1>&2
|
||||||
MOUNT="sudo /usr/local/sysadmin/utils/manage_rubrik_restore_mvs.ksh"
|
echo "Format Timestamp YYYY-MM-DD HH:MM:SS"
|
||||||
UMOUNT="sudo /usr/local/sysadmin/utils/manage_rubrik_restore_mvs.ksh"
|
exit 1; }
|
||||||
|
|
||||||
usage() { echo "Usage: $0 <-d DBNAME> <-t \"timestamp\"> <-g tgthost || -r rachost> [-h <dbhost>] [-o <oracle_home>] [-m <mountpoint> [-l|-n]" 1>&2; exit 1; }
|
filesonly=false
|
||||||
|
|
||||||
filesonly=true
|
while getopts "h:d:f" o; do
|
||||||
|
|
||||||
while getopts "d:t:g:r:m:h:o:ln" o; do
|
|
||||||
case "${o}" in
|
case "${o}" in
|
||||||
d)
|
|
||||||
RBK_SID=${OPTARG}
|
|
||||||
;;
|
|
||||||
t)
|
|
||||||
datestring=${OPTARG}
|
|
||||||
;;
|
|
||||||
g)
|
|
||||||
RBK_TGT=${OPTARG}
|
|
||||||
;;
|
|
||||||
r)
|
|
||||||
RAC_TGT=${OPTARG}
|
|
||||||
;;
|
|
||||||
m)
|
|
||||||
mountpoint=${OPTARG}
|
|
||||||
;;
|
|
||||||
h)
|
h)
|
||||||
RBK_HOST=${OPTARG}
|
RBK_HOST=${OPTARG}
|
||||||
;;
|
;;
|
||||||
o)
|
f)
|
||||||
|
filesonly=true
|
||||||
|
;;
|
||||||
|
d)
|
||||||
oraclehome=${OPTARG}
|
oraclehome=${OPTARG}
|
||||||
;;
|
;;
|
||||||
l)
|
|
||||||
filesonly=false
|
|
||||||
;;
|
|
||||||
n)
|
|
||||||
nowait=true
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
*)
|
||||||
usage
|
usage
|
||||||
;;
|
;;
|
||||||
@@ -61,204 +39,69 @@ while getopts "d:t:g:r:m:h:o:ln" o; do
|
|||||||
done
|
done
|
||||||
shift $((OPTIND-1))
|
shift $((OPTIND-1))
|
||||||
|
|
||||||
if [ -z "${RBK_SID}" ] || [ -z "${datestring}" ]; then
|
RBK_SID=$1
|
||||||
|
|
||||||
|
if [ -z "${RBK_SID}" ]; then
|
||||||
usage
|
usage
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#if [ -z "${RAC_TGT}" ] && [ -z "${RBK_TGT}" ]; then
|
RBK_SID=$1
|
||||||
# usage
|
RBK_TGT=$2
|
||||||
#fi
|
|
||||||
|
|
||||||
if [ -n "${RBK_TGT}" ] && [ -n "${RAC_TGT}" ]; then
|
|
||||||
echo "ERROR: Specify either -g or -r, not both"
|
|
||||||
usage
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${mountpoint}" ]; then
|
|
||||||
mountpoint=/rbk
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo Connecting to Rubrik with IP $RUBRIK_IP
|
echo Connecting to Rubrik with IP $RUBRIK_IP
|
||||||
|
|
||||||
# API call to list Oracle DBs
|
# API call to list Oracle DBs
|
||||||
find_database
|
find_database
|
||||||
|
|
||||||
mount_mv () {
|
# API call to get the host ID of the target
|
||||||
|
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/host?name=$RBK_TGT"
|
||||||
|
rest_api_get
|
||||||
|
|
||||||
utctime=$($DATE -d"$datestring" +"%Y-%m-%d %H:%M:%S")
|
total=$(cat /tmp/rbkresponse.$$ | jq -r .total)
|
||||||
if [ $? -ne 0 ]; then
|
if [ $total -ne 1 ]; then
|
||||||
echo ERROR: Unable to convert supplied timestamp to UTC time
|
echo Target host name of $RBK_TGT does not map to a single host:
|
||||||
exit_with_error
|
|
||||||
fi
|
|
||||||
echo INFO: Requested time is $datestring which is $utctime in UTC
|
|
||||||
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume/$mvData/snapshot"
|
|
||||||
rest_api_get
|
|
||||||
|
|
||||||
# Select snapshot of data volume with timestamp before requested time
|
|
||||||
read mvDataSnap dtDataSnap < <(echo $(jq -r --arg t "$utctime" '
|
|
||||||
[($t) | strptime("%Y-%m-%d %H:%M:%S")] as $r
|
|
||||||
| .data | map(select(
|
|
||||||
(.date[:19] | strptime("%Y-%m-%dT%H:%M:%S")) as $d
|
|
||||||
| $d <= $r[0]
|
|
||||||
)) | sort_by(.date) | last | "\(.id) \(.date)"' /tmp/rbkresponse.$$))
|
|
||||||
|
|
||||||
echo Snapshot ID to mount is $mvDataSnap from $dtDataSnap
|
|
||||||
|
|
||||||
# List MVs for logs volume
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume/$mvLogs/snapshot"
|
|
||||||
rest_api_get
|
|
||||||
|
|
||||||
# Select snapshot of logs volume with timestamp after requested time
|
|
||||||
read mvLogsSnap dtLogsSnap < <(echo $(jq -r --arg t "$utctime" '
|
|
||||||
[($t) | strptime("%Y-%m-%d %H:%M:%S")] as $r
|
|
||||||
| .data | map(select(
|
|
||||||
(.date[:19] | strptime("%Y-%m-%dT%H:%M:%S")) as $d
|
|
||||||
| $d >= $r[0]
|
|
||||||
)) | sort_by(.date) | first | "\(.id) \(.date)"' /tmp/rbkresponse.$$))
|
|
||||||
|
|
||||||
echo Snapshot ID of Logs Volume to mount is $mvLogsSnap from $dtLogsSnap
|
|
||||||
|
|
||||||
if [ -z "${RBK_TGT}" ]; then
|
|
||||||
clients=$(hostname)
|
|
||||||
echo INFO: hostname $clients is not fully qualified, adding domain name to it. Use -g flag to override client name pattern
|
|
||||||
clients=$(hostname).$(domainname)
|
|
||||||
else
|
|
||||||
clients=${RBK_TGT}
|
|
||||||
fi
|
|
||||||
|
|
||||||
PAYLOAD="{\"hostPatterns\":[\"$clients\"]}"
|
|
||||||
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume/snapshot/$mvDataSnap/export"
|
|
||||||
rest_api_post
|
|
||||||
DATA_ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href')
|
|
||||||
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume/snapshot/$mvLogsSnap/export"
|
|
||||||
rest_api_post
|
|
||||||
LOGS_ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href')
|
|
||||||
|
|
||||||
datajobdone=0
|
|
||||||
logsjobdone=0
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
if [ $datajobdone -eq 0 ]; then
|
|
||||||
ENDPOINT=$DATA_ENDPOINT
|
|
||||||
rest_api_get
|
|
||||||
datastatus=$(cat /tmp/rbkresponse.$$ | jq -r '.status')
|
|
||||||
echo "INFO: Data Mount status is $datastatus"
|
|
||||||
if [[ $datastatus =~ SUCCEEDED|FAILED|CANCELED ]]; then
|
|
||||||
datajobdone=1
|
|
||||||
dataExport=$(cat /tmp/rbkresponse.$$ | jq -r ' .links | .[] | select(.rel=="result") .href')
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $logsjobdone -eq 0 ]; then
|
|
||||||
ENDPOINT=$LOGS_ENDPOINT
|
|
||||||
rest_api_get
|
|
||||||
logsstatus=$(cat /tmp/rbkresponse.$$ | jq -r '.status')
|
|
||||||
echo "INFO: Logs Mount status is $logsstatus"
|
|
||||||
if [[ $logsstatus =~ SUCCEEDED|FAILED|CANCELED ]]; then
|
|
||||||
logsjobdone=1
|
|
||||||
logsExport=$(cat /tmp/rbkresponse.$$ | jq -r ' .links | .[] | select(.rel=="result") .href')
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $logsjobdone -eq 1 ] && [ $datajobdone -eq 1 ]; then
|
|
||||||
echo Data Export details
|
|
||||||
ENDPOINT=$dataExport
|
|
||||||
rest_api_get
|
|
||||||
dataMounts=$(cat /tmp/rbkresponse.$$ | jq -r '.channels[] | ( .ipAddress + ":" + .mountPoint)')
|
|
||||||
ENDPOINT=$logsExport
|
|
||||||
rest_api_get
|
|
||||||
logMounts=$(cat /tmp/rbkresponse.$$ | jq -r '.channels[] | ( .ipAddress + ":" + .mountPoint)')
|
|
||||||
for mountPath in $dataMounts $logMounts; do
|
|
||||||
leaf=$(echo $mountPath | cut -d/ -f4)
|
|
||||||
echo creating folder and mounting $mountPath at $mountpoint/$RBK_SID/$leaf
|
|
||||||
mkdir -p $mountpoint/$RBK_SID/$leaf
|
|
||||||
$MOUNT $mountPath $mountpoint/$RBK_SID/$leaf
|
|
||||||
done
|
|
||||||
|
|
||||||
cleanup
|
|
||||||
exit
|
|
||||||
else
|
|
||||||
sleep 10
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
mount_snappable () {
|
|
||||||
|
|
||||||
if [ "$dg_type" == "DataGuardMember" ]; then
|
|
||||||
echo Initiating mount from source $RBK_SID \($grp_name\)
|
|
||||||
else
|
|
||||||
[[ $rac_name != "null" ]] && [[ -n "$rac_name" ]] && string=$rac_name || string=$RBK_HOST
|
|
||||||
echo Initiating mount from source $RBK_SID on $string
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${RBK_TGT}" ]; then
|
|
||||||
# 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 ERROR: Target host name of $RBK_TGT does not map to a single host.
|
|
||||||
echo ERROR: Matching hosts are listed here. Please re-run using one of the following:
|
|
||||||
cat /tmp/rbkresponse.$$ | jq -r '.data[].name'
|
cat /tmp/rbkresponse.$$ | jq -r '.data[].name'
|
||||||
exit_with_error
|
exit_with_error
|
||||||
fi
|
fi
|
||||||
|
|
||||||
target_id=$(cat /tmp/rbkresponse.$$ | jq -r '.data[0].id')
|
target_id=$(cat /tmp/rbkresponse.$$ | jq -r '.data[0].id')
|
||||||
else
|
|
||||||
# API call to get the host ID of the target
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/rac?name=$RAC_TGT"
|
|
||||||
rest_api_get
|
|
||||||
|
|
||||||
total=$(cat /tmp/rbkresponse.$$ | jq -r .total)
|
# convert datestamp from string into milliseconds
|
||||||
if [ $total -ne 1 ]; then
|
datestring=$3
|
||||||
echo ERROR: Target RAC Cluster name of $RAC_TGT does not map to a single entity:
|
|
||||||
echo ERROR: Matching clusters are listed here. Please re-run using one of the following:
|
|
||||||
cat /tmp/rbkresponse.$$ | jq -r '.data[].name'
|
|
||||||
exit_with_error
|
|
||||||
fi
|
|
||||||
|
|
||||||
target_id=$(cat /tmp/rbkresponse.$$ | jq -r '.data[0].id')
|
echo requested timestamp is $datestring
|
||||||
fi
|
|
||||||
|
|
||||||
# convert datestamp from string into milliseconds
|
ts=$(date -d"$datestring" +%s)
|
||||||
echo requested timestamp is $datestring
|
if [ $? -ne 0 ]; then
|
||||||
|
|
||||||
ts=$(date -d"$datestring" +%s)
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo Problem with timestamp
|
echo Problem with timestamp
|
||||||
exit_with_error
|
exit_with_error
|
||||||
fi
|
fi
|
||||||
((millis = $ts * 1000))
|
((millis = $ts * 1000))
|
||||||
|
|
||||||
if [ ! -z ${oraclehome+x} ]; then
|
if [ ! -z ${oraclehome+x} ]; then
|
||||||
configmap="\"ORACLE_HOME\":\"$oraclehome\""
|
configmap="\"ORACLE_HOME\":\"$oraclehome\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# API call to perform the mount
|
# API call to perform the mount
|
||||||
PAYLOAD="{\"recoveryPoint\":{\"timestampMs\":$millis},\"targetOracleHostOrRacId\":\"$target_id\",\"targetMountPath\":\"$mountpoint\",\"shouldMountFilesOnly\":$filesonly,\"advancedRecoveryConfigMap\":{$configmap}}"
|
PAYLOAD="{\"recoveryPoint\":{\"timestampMs\":$millis},\"targetOracleHostOrRacId\":\"$target_id\",\"targetMountPath\":\"/rbk/\",\"shouldMountFilesOnly\":$filesonly,\"advancedRecoveryConfigMap\":{$configmap}}"
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/mount"
|
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/mount"
|
||||||
|
|
||||||
rest_api_post
|
rest_api_post
|
||||||
|
|
||||||
ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href')
|
ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href')
|
||||||
LOOP=0
|
LOOP=0
|
||||||
while true; do
|
while true; do
|
||||||
rest_api_get
|
rest_api_get
|
||||||
status=$(cat /tmp/rbkresponse.$$ | jq -r '.status')
|
status=$(cat /tmp/rbkresponse.$$ | jq -r '.status')
|
||||||
if [ $status != "SUCCEEDED" ] && [ $status != "FAILED" ]; then
|
if [ $status != "SUCCEEDED" ] && [ $status != "FAILED" ]; then
|
||||||
echo Status is $status, checking in 15 seconds
|
echo Status is $status, checking in 10 seconds
|
||||||
if [ $status = "RUNNING" ] && [ ${LOOP} -ne 1 ] ; then
|
if [ $status = "RUNNING" ] && [ ${LOOP} -ne 1 ] ; then
|
||||||
LOOP=1
|
LOOP=1
|
||||||
sleep 5
|
sleep 5
|
||||||
save=$ENDPOINT
|
save=$ENDPOINT
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount?source_database_name=$dbname"
|
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/mount?source_database_name=$dbname"
|
||||||
rest_api_get
|
rest_api_get
|
||||||
|
# cat /tmp/rbkresponse.$$ | jq -r '.data[]'
|
||||||
RBK_ID_LV=$(cat /tmp/rbkresponse.$$ | jq -r '.data[] | select(.status=="Mounting") | .id')
|
RBK_ID_LV=$(cat /tmp/rbkresponse.$$ | jq -r '.data[] | select(.status=="Mounting") | .id')
|
||||||
ENDPOINT=$save
|
ENDPOINT=$save
|
||||||
fi
|
fi
|
||||||
@@ -270,18 +113,10 @@ mount_snappable () {
|
|||||||
echo LIVE MOUNT SUCCEEDED
|
echo LIVE MOUNT SUCCEEDED
|
||||||
echo "The live mount id is: ${RBK_ID_LV}"
|
echo "The live mount id is: ${RBK_ID_LV}"
|
||||||
# cat /tmp/rbkresponse.$$ | jq -r ' '
|
# cat /tmp/rbkresponse.$$ | jq -r ' '
|
||||||
cleanup
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
sleep 15
|
sleep 10
|
||||||
done
|
done
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$db_id" == "ManagedVolume" ]; then
|
|
||||||
mount_mv
|
|
||||||
else
|
|
||||||
mount_snappable
|
|
||||||
fi
|
|
||||||
|
|
||||||
cleanup
|
cleanup
|
||||||
|
|||||||
Reference in New Issue
Block a user