Clone from Primary to Standby Environment Daily After Daily Maintenance is Complete on the Primary Environment

To keep the standby environment up to date with the primary environment, use these scripts to clone Oracle Fusion Cloud Enterprise Performance Management primary environment to the standby environment soon after the daily maintenance is complete on the primary environment.

These custom scripts identify whether the scheduled daily maintenance for the day is complete and then clone the environment.

Windows Script

Create dailyclone.ps1 by copying the following PowerShell script.
# Clone Environment script
#
# Update the following parameters
# -------------------------------
$users_and_predefined_roles="false"
$daily_maintenance_start_time="true"
$data_management="true"
$app_audit="true"
$job_console="true"
$stored_snapshots_and_files="false"
# -------------------------------

$source_username=$args[0]
$source_password=$args[1]
$source_url=$args[2]
$target_username=$args[3]
$target_password=$args[4]
$target_url=$args[5]

if ($($args.count) -ne 6) {
    echo "Usage: ./dailyclone.ps1 <SOURCE USERNAME> <SOURCE PASSWORD> <SOURCE URL> <TARGET USERNAME> <TARGET PASSWORD> <TARGET URL>"
    exit 1
}

$amw_time=""

function getDailyMaintenanceStartTime {
    $amwstring=$(epmautomate.bat getDailyMaintenanceStartTime)
    $elements=$amwstring.split(' ')
    $amwtime=$elements[0]
    return $amwtime
}

function goToSleep ($amw_time){
    $current_mdy=Get-Date -AsUTC -UFormat "%m/%d/%Y"
    $current_date_time=Get-Date -AsUTC -UFormat "%m/%d/%Y %H:%M:%S"
    $current_epoch=Get-Date -Date $current_date_time -UFormat "%s"
    $target_date_time=[DateTime]"${current_mdy} ${amw_time}"
    $target_epoch=Get-Date -Date $target_date_time -UFormat "%s"
    $sleep_seconds=$target_epoch - $current_epoch

    # Today's AMW start time has already passed, so add 24 hours to sleep_seconds
    if ($sleep_seconds -lt 0) {
        $sleep_seconds=$sleep_seconds + 86400
    }

    $sleep_ts=New-TimeSpan -Seconds ${sleep_seconds}
    $sleep_hms="${sleep_ts}" -replace '^\d+?\.'

    echo "Current time is ${current_date_time}. Sleeping for ${sleep_hms}, until daily maintenance start time of ${amw_time}."
    Start-Sleep -Seconds $sleep_seconds
}

function deleteArtifactSnapshotIfExists {
    if (artifactSnapshotExists) {
        $command_del=$(epmautomate.bat deletefile "Artifact Snapshot")
    }
}

function artifactSnapshotExists {
    $filelist=$(epmautomate.bat listfiles)
    if ("$filelist".contains("Artifact Snapshot")) {
        return $true
    else
        return $false
    }
}

function cloneEnvironment {
    echo "Checking to see if daily maintenance processing has completed ..."
    while ($true) {
        if (artifactSnapshotExists) {
            echo "Daily maintenance processing has completed ..."
            break
	} else {
            echo "Sleeping for 30 seconds before the next check to see if daily maintenance processing has completed ..."
            Start-Sleep -Seconds 30
        }
    }

    echo "Encrypting target password ..."
    epmautomate.bat encrypt "${target_password}" "oracleKey" "target_password.epw"

    echo "Cloning environment ..."
    epmautomate.bat cloneEnvironment "${target_username}" "target_password.epw" "${target_url}" "SnapshotName=Artifact Snapshot" "UsersAndPreDefinedRoles=${users_and_predefined_roles}" "DataManagement=${data_management}" "appAudit=${app_audit}" "jobConsole=${job_console}" "storedSnapshotsAndFiles=${stored_snapshots_and_files}" "dailyMaintenanceStartTime=${daily_maintenance_start_time}"
}

echo "Beginning clone environment script."
echo "Logging into server ..."
epmautomate.bat login ${source_username} ${source_password} ${source_url}
$amwtime=getDailyMaintenanceStartTime
goToSleep ($amwtime)
deleteArtifactSnapshotIfExists
cloneEnvironment
echo "Logging out of server ..."
epmautomate.bat logout
echo "Clone environment script processing has completed."

Linux/UNIX Script

Create dailyclone.sh by copying the following script.
#!/bin/bash

# Update the following parameters
# -------------------------------
epmautomatescript="LOCATION_EPM_AUTOMATE_EXECUTABLE"
javahome="LOCATION_JAVA_HOME"
users_and_predefined_roles="false"
data_management="true"
app_audit="true"
job_console="true"
stored_snapshots_and_files="false"
daily_maintenance_start_time="true"
# -------------------------------

source_username="$1"
source_password="$2"
source_url="$3"
target_username="$4"
target_password="$5"
target_url="$6"

export JAVA_HOME=${javahome}

if [ "$#" -ne 6 ]; then
    echo "Usage: ./dailyclone.sh SOURCE_USERNAME SOURCE_PASSWORD SOURCE_URL TARGET_USERNAME TARGET_PASSWORD TARGET_URL"
    exit 1
fi

amw_time=""

getDailyMaintenanceStartTime() {
    amw_time=$(${epmautomatescript} getDailyMaintenanceStartTime | cut -d' ' -f1)
}

goToSleep() {
    current_mdy=$(date -u +%m/%d/%Y)
    current_date_time=$(date -u)
    current_epoch=$(date +%s)
    target_epoch=$(date -d "${current_mdy} ${amw_time}" +%s)
    sleep_seconds=$(($target_epoch - $current_epoch))

    # Today's AMW start time has already passed, so add 24 hours to sleep_seconds
    if [[ ${sleep_seconds} -lt 0 ]]
    then
        sleep_seconds=$((sleep_seconds + 86400))
    fi

    sleep_hms=$(date -d@${sleep_seconds} -u +%H:%M:%S)

    echo "Current time is ${current_date_time}. Sleeping for ${sleep_hms}, until daily maintenance start time of ${amw_time}."
    sleep $sleep_seconds
}

deleteArtifactSnapshotIfExists() {
    found=1
    filelist=$(${epmautomatescript} listfiles)
    if [[ ${filelist} == *"Artifact Snapshot"* ]]
    then
        command_del=$(${epmautomatescript} deletefile "Artifact Snapshot")
    fi
}

artifactSnapshotExists() {
    found=1

    filelist=$(${epmautomatescript} listfiles)
    if [[ ${filelist} == *"Artifact Snapshot"* ]]
    then
        found=0
    else
        found=1
    fi

    echo ${found}
}

cloneEnvironment() {
    local found=1

    while true
    do
        found=$(artifactSnapshotExists)
        if [[ ${found} -eq 0 ]]
        then
            echo "Daily maintenance processing has completed ..."
            break
        else
            echo "Sleeping for 30 seconds before the next check to see if daily maintenance processing has completed ..."
            sleep 30
        fi
    done

    echo "Encrypting target password ..."
    ${epmautomatescript} encrypt "${target_password}" "oracleKey" "target_password.epw"

    echo "Cloning environment ..."
    ${epmautomatescript} cloneEnvironment "${target_username}" "target_password.epw" "${target_url}" "SnapshotName=Artifact Snapshot" "UsersAndPreDefinedRoles=${users_and_predefined_roles}" "DataManagement=${data_management}" "appAudit=${app_audit}" "jobConsole=${job_console}" "storedSnapshotsAndFiles=${stored_snapshots_and_files}" "dailyMaintenanceStartTime=${daily_maintenance_start_time}"
}

echo "Beginning clone environment script."
echo "Logging into server ..."
${epmautomatescript} login ${source_username} ${source_password} ${source_url}
getDailyMaintenanceStartTime
goToSleep
deleteArtifactSnapshotIfExists
cloneEnvironment
echo "Logging out of server ..."
${epmautomatescript} logout
echo "Clone environment script processing has completed."

Groovy Script

Create dailyclone groovy script by copying the following code.
// Clone Environment script

// Update the following parameters
String source_username="USERNAME"
String source_password="PASSWORD!"
String source_url="URL OF THE SOURCE ENVIRONMENT"
String target_username="USERNAME"
String target_password="PASSWORD"
String target_url="URL OF THE TARGET ENVIRONMENT"
String snapshot_name="Artifact Snapshot"

// -------------------------------

// Do not update the following parameters
String users_and_predefined_roles="false"
String data_management="true"
String app_audit="true"
String job_console="true"
String stored_snapshots_and_files="false"
String daily_maintenance_start_time="true"
// -------------------------------

def LogMessage(String message) {
    def date = new Date()
    def sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss")
    println('[' + sdf.format(date) + '] ' + message);
}

def LogOperationStatus(EpmAutomateStatus opstatus) {
    def returncode = opstatus.getStatus()
    if (returncode != 0){
        LogMessage(opstatus.getOutput())
    }
    LogMessage('return code: ' + returncode)
}

def getDailyMaintenanceStartTime(EpmAutomate automate) {
    LogMessage("Operation: getDailyMaintenanceStartTime")
    EpmAutomateStatus amwtimestatus = automate.execute('getDailyMaintenanceStartTime')
    LogOperationStatus(amwtimestatus)
    def amwstring=(amwtimestatus.getOutput())
    def elements=amwstring.split(' ')
    def amwtime=elements[0]
    return amwtime
}

def goToSleep(String amw_time){
    def date = new Date()
    def current_mdy = new SimpleDateFormat("MM/dd/yyyy")
    def current_date_time = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss")
    float current_epoch = date.getTime() / 1000
    def pattern = "MM/dd/yyyy HH:mm:ss"
    def input = current_mdy.format(date) + " " + amw_time + ":00"
    def target_date_time = Date.parse(pattern, input)
    float target_epoch = target_date_time.getTime() / 1000
    int sleep_seconds = Math.round(target_epoch - current_epoch)

    //Today's AMW start time has already passed, so add 24 hours to sleep_seconds
    if (sleep_seconds < 0) {
        sleep_seconds = sleep_seconds + 86400
    }
    
    def sleep_milliseconds = sleep_seconds * 1000
    LogMessage("Current time is " + current_date_time.format(date) + ". Sleeping until daily maintenance start time of " + amw_time + ":00.")
    sleep(sleep_milliseconds)
}

boolean artifactSnapshotExists(EpmAutomate automate,String snapshot_name) {
    LogMessage("Operation: listfiles")
    EpmAutomateStatus listfilesstatus = automate.execute('listfiles')
    String filelist=(listfilesstatus.getItemsList())
    LogOperationStatus(listfilesstatus)
    
    if (filelist.contains(snapshot_name)) {
        return true
    } else {
        return false
    }
}

def deleteArtifactSnapshotIfExists(EpmAutomate automate,String snapshot_name){
    if (artifactSnapshotExists(automate,snapshot_name)) {
        LogMessage("Operation: deletefile " + snapshot_name)
        EpmAutomateStatus deletefilestatus = automate.execute('deletefile',snapshot_name)
        LogOperationStatus(deletefilestatus)
    }
}

def waitForDailyMaintenanceToComplete(EpmAutomate automate,String snapshot_name) {
    LogMessage("Checking to see if daily maintenance processing has completed ...")
    while (true) {
        if (artifactSnapshotExists(automate,snapshot_name)) {
            LogMessage("Daily maintenance processing has completed ...")
            break
        } else {
            LogMessage("Sleeping for 30 seconds before the next check to see if daily maintenance processing has completed ...")
            sleep(30000)
        }
    }
}

LogMessage("Clone environment script processing beginning ...")

EpmAutomate automate = getEpmAutomate()

LogMessage("Operation: login " + source_username + " " + source_password + " " + source_url)
EpmAutomateStatus status = automate.execute('login',source_username,source_password,source_url)
LogOperationStatus(status)

String amwtime = getDailyMaintenanceStartTime(automate)
goToSleep (amwtime)
deleteArtifactSnapshotIfExists(automate,snapshot_name)
waitForDailyMaintenanceToComplete(automate,snapshot_name)

LogMessage("Operation: encrypt " + target_password + " oracleKey target_password.epw")
status = automate.execute('encrypt',target_password,'oracleKey','target_password.epw')
LogOperationStatus(status)

LogMessage("Operation: cloneEnvironment " + target_username + " target_password.epw " + target_url + " SnapshotName=" + snapshot_name + " UsersAndPreDefinedRoles=" + users_and_predefined_roles + " DataManagement=" + data_management + " appAudit=" + app_audit + " jobConsole=" + job_console + " storedSnapshotsAndFiles=" + stored_snapshots_and_files + " dailyMaintenanceStartTime=" + daily_maintenance_start_time)
EpmAutomateStatus cloneenvironmentstatus = automate.execute('cloneEnvironment',target_username,"target_password.epw",target_url,"SnapshotName=" + snapshot_name,"UsersAndPreDefinedRoles=" + users_and_predefined_roles,"DataManagement=" + data_management,"appAudit=" + app_audit,"jobConsole=" + job_console,"storedSnapshotsAndFiles=" + stored_snapshots_and_files,"dailyMaintenanceStartTime=" + daily_maintenance_start_time)
LogOperationStatus(cloneenvironmentstatus)

LogMessage("Operation: logout ")
status = automate.execute('logout')
LogOperationStatus(status)

LogMessage ("Clone environment script processing has completed.")

Running the Script

  1. Create dailyclone.ps1, dailyclone.sh, or the dailyclone groovy script by copying a script from one of the preceding sections.
  2. Update the scripts:

    Update for dailyclone.sh:

    • epmautomatescript with the location of the EPM Automate executable. Example: epmautomatescript="/home/utils/EPMAutomate/bin/epmautomate.sh"
    • javahome with the directory where the JDK used by EPM Automate is installed. For example: "/home/user1/jdk_17.0.12"
    Update for dailyclone.ps1 and dailyclone.sh:
    • users_and_predefined_roles: Set this value to true to clone users and their predefined role assignments (Access Control groups are always cloned).
    • data_management: Set this value to false to not clone Data Integration records. Note that Data Integration records can be cloned only if both the source and target environments are on the same monthly update or the target environment is one update newer than the source environment. For example, you can clone 22.01 Data Management records to another 22.01 environment or to a 22.02 environment only.

      Ignored for Narrative Reporting and Oracle Fusion Cloud Enterprise Data Management environments.

    • app_audit: Set this value to false if you do not want to clone the application audit data for Planning, FreeForm, and Enterprise Profitability and Cost Management applications.

      Financial Consolidation and Close and Tax Reporting audit information is always cloned.

    • job_console: Set this value to false if you do not want to clone job console data.
    • stored_snapshots_and_files: Set this value to true if you want to clone the contents of the top level folders in the inbox and outbox (subfolders are never cloned) of the source environment.
    • daily_maintenance_start_time: Set this value to false if you do not want to reset the maintenance start time of the cloned target environment to that of the source environment.
    Updates for dailyclone groovy script:
    • source_username is the user name of a Service Administrator. The Identity Domain Administrator role is required to clone users and predefined roles.
    • source_password is the password of the user identified by SOURCE_USERNAME.
    • source_url is the URL of the environment that you want to clone.
    • target_username is the user name of a Service Administrator. The Identity Domain Administrator role is required to clone users and predefined roles.
    • target_password is the password of the user identified by TARGET_USERNAME.
    • target_URL is the URL of the target environment.
  3. Run dailyclone.ps1, dailyclone.sh or the dailyclone groovy script:

    Windows

    • In a Command Window, navigate to the folder where dailyclone.ps1 is stored.
    • Execute the command: ./dailyclone.ps1 SOURCE_USERNAME SOURCE_PASSWORD SOURCE_URL TARGET_USERNAME TARGET_PASSWORD TARGET_URL. See the following table for descriptions of these values.

    Table 3-7 Description of Parameters

    Parameter Description
    SOURCE_USERNAME User name of a Service Administrator.Additionally, this user must have the Identity Domain Administrator role to clone users and predefined roles.
    SOURCE_PASSWORD The password of the user identified by SOURCE_USERNAME.
    SOURCE_URL The URL of the environment that you want to clone.
    TARGET_USERNAME The user name of a Service Administrator in the target environment. Additionally, this user must have the Identity Domain Administrator role to clone users and predefined roles.
    TARGET_PASSWORD The password of the user identified by TARGET_USERNAME.
    TARGET_URL The URL of the target environment.
    Linux/UNIX
    • In a UNIX or Linux shell, navigate to the directory where dailyclone.sh is stored.
    • Execute the command: ./dailyclone.sh SOURCE_USERNAME SOURCE_PASSWORD SOURCE_URL TARGET_USERNAME TARGET_PASSWORD TARGET_URL. See the preceding table for descriptions of these values.
    Groovy

    See Running Commands without Installing EPM Automate.