Finished clone script
This commit is contained in:
114
oracle_clone.sh
114
oracle_clone.sh
@@ -1,40 +1,57 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Perform a Live Mount of an Oracle DB
|
||||
# v0.2 - James Pattinson - August 2021
|
||||
# Perform a Clone of an Oracle DB
|
||||
# v1.0 - James Pattinson - October 2025
|
||||
#
|
||||
# usage: oracle_mount.sh [-h <dbhost>] [-d <oracle_home> [-f] [-t <timestamp>] <srcSID> <tgtHOSTNAME>
|
||||
# usage: oracle_clone.sh [options] <srcSID> <tgtHOSTNAME>
|
||||
#
|
||||
# -d specify $ORACLE_HOME on target - needed for mount of Data Guard DBs
|
||||
# -f mount files only - do not create database
|
||||
# Options:
|
||||
# -h <dbhost> Source DB hostname
|
||||
# -t <timestamp> Recovery point timestamp "YYYY-MM-DD HH:MM:SS" (uses latest if not specified)
|
||||
# -n <newsid> New database SID for the clone
|
||||
# -p <pfilepath> Custom pfile for the clone
|
||||
# -a <key,value> Advanced Cloning Options (can be used multiple times)
|
||||
# -d Dry run mode - show API payload without executing
|
||||
#
|
||||
# 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"
|
||||
usage() { echo "Usage: $0 [options] <srcSID> <tgtHOSTNAME>" 1>&2
|
||||
echo "Options:" 1>&2
|
||||
echo " -h <dbhost> Source DB hostname" 1>&2
|
||||
echo " -t <timestamp> Recovery point \"YYYY-MM-DD HH:MM:SS\"" 1>&2
|
||||
echo " -n <newsid> New database SID for clone" 1>&2
|
||||
echo " -p <pfilepath> Custom pfile for the clone" 1>&2
|
||||
echo " -a <key,value> Advanced Cloning Options (can be used multiple times)" 1>&2
|
||||
echo " -d Dry run mode" 1>&2
|
||||
exit 1; }
|
||||
|
||||
filesonly=false
|
||||
declare -a config_pairs
|
||||
dryrun=false
|
||||
|
||||
while getopts "h:d:t:f" o; do
|
||||
while getopts "h:dt:n:p:a:" o; do
|
||||
case "${o}" in
|
||||
h)
|
||||
RBK_HOST=${OPTARG}
|
||||
;;
|
||||
f)
|
||||
filesonly=true
|
||||
;;
|
||||
d)
|
||||
oraclehome=${OPTARG}
|
||||
;;
|
||||
t)
|
||||
datestring=${OPTARG}
|
||||
;;
|
||||
n)
|
||||
newsid=${OPTARG}
|
||||
;;
|
||||
p)
|
||||
custompfile=${OPTARG}
|
||||
;;
|
||||
a)
|
||||
config_pairs+=("${OPTARG}")
|
||||
;;
|
||||
d)
|
||||
dryrun=true
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
@@ -43,14 +60,12 @@ done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
RBK_SID=$1
|
||||
RBK_TGT=$2
|
||||
|
||||
if [ -z "${RBK_SID}" ]; then
|
||||
if [ -z "${RBK_SID}" ] || [ -z "${RBK_TGT}" ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
RBK_SID=$1
|
||||
RBK_TGT=$2
|
||||
|
||||
echo Connecting to Rubrik with IP $RUBRIK_IP
|
||||
|
||||
# API call to list Oracle DBs
|
||||
@@ -85,17 +100,42 @@ if [ $? -ne 0 ]; then
|
||||
fi
|
||||
((millis = $ts * 1000))
|
||||
|
||||
exit
|
||||
configmap=""
|
||||
# Build configmap from -a options
|
||||
for pair in "${config_pairs[@]}"; do
|
||||
key=$(echo "$pair" | cut -d',' -f1)
|
||||
value=$(echo "$pair" | cut -d',' -f2-)
|
||||
echo "ACO: $key = $value"
|
||||
if [ -n "$configmap" ]; then
|
||||
configmap="$configmap,"
|
||||
fi
|
||||
configmap="$configmap\"$key\":\"$value\""
|
||||
done
|
||||
|
||||
if [ ! -z ${oraclehome+x} ]; then
|
||||
configmap="\"ORACLE_HOME\":\"$oraclehome\""
|
||||
# Build the payload
|
||||
PAYLOAD="{\"recoveryPoint\":{\"timestampMs\":$millis},\"targetOracleHostOrRacId\":\"$target_id\",\"shouldRestoreFilesOnly\":false"
|
||||
|
||||
if [ -n "$newsid" ]; then
|
||||
PAYLOAD="$PAYLOAD,\"cloneDbName\":\"$newsid\""
|
||||
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"
|
||||
if [ -n "$custompfile" ]; then
|
||||
PAYLOAD="$PAYLOAD,\"customPfilePath\":\"$custompfile\""
|
||||
fi
|
||||
|
||||
rest_api_post
|
||||
PAYLOAD="$PAYLOAD,\"advancedRecoveryConfigMap\":{$configmap}}"
|
||||
|
||||
ENDPOINT="https://$RUBRIK_IP/api/internal/oracle/db/$db_id/export"
|
||||
|
||||
echo "$PAYLOAD" > /tmp/payload.$$
|
||||
|
||||
if [ "$dryrun" = true ]; then
|
||||
echo "Dry run mode - API payload that would be sent:"
|
||||
echo $PAYLOAD | jq
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rest_api_post_file
|
||||
|
||||
ENDPOINT=$(cat /tmp/rbkresponse.$$ | jq -r '.links[0].href')
|
||||
LOOP=0
|
||||
@@ -104,28 +144,18 @@ while true; do
|
||||
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
|
||||
echo CLONE FAILED WITH STATUS $status
|
||||
cat /tmp/rbkresponse.$$ | jq
|
||||
exit_with_error
|
||||
else
|
||||
echo LIVE MOUNT SUCCEEDED
|
||||
echo "The live mount id is: ${RBK_ID_LV}"
|
||||
# cat /tmp/rbkresponse.$$ | jq -r ' '
|
||||
echo CLONE SUCCEEDED
|
||||
cat /tmp/rbkresponse.$$ | jq
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
|
||||
cleanup
|
||||
cleanup
|
||||
Reference in New Issue
Block a user