Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps-unlimited/EBSR12.2onOCI/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Binary file not shown.
Binary file added apps-unlimited/EBSR12.2onOCI/.vs/slnx.sqlite
Binary file not shown.
1 change: 1 addition & 0 deletions apps-unlimited/EBSR12.2onOCI/AppTier/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

109 changes: 109 additions & 0 deletions apps-unlimited/EBSR12.2onOCI/AppTier/ChangeHomePath.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#############################################################################
# ChangeHomePath.sh
#
# Copyright (c) 2025 Oracle and/or its affiliates
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
#
# An include script holding the common routine that changes the oracle
# database home path if needed when switching a standby database to primary.
#
# This is an INCLUDE file. It is code to be included in an outer ksh
# script. It just holds the routine ReConfig, which calls the EBS code.
# It does not need a shebang, as it is simply a part of a larger program.
#
# Note: assumes all the database instances are present in gv_instance when
# the check is done in the main script.
#
# Requires user equivalency across all RAC nodes.
#
# No parameters passed in
#
# Rev:
# 8/23/24 Re-formed as a standard routine to execute from different scripts
# 1/15/24 Created
#############################################################################
ReConfig()
{
LogMsg "Started ReConfig - Database Home Reconfiguration"

LogMsg "DbName: $DbName"

# Calling script has the apps password. Need to get the database password
GetLogon $DB_SECRET_NAME
DB_SECRET=$LOGON

PERLBIN=`dirname $ORACLE_HOME/perl/bin/perl`
LogMsg "PERLBIN = $PERLBIN"

PATH=${PERLBIN}:${PATH}

PERL5LIB=$ORACLE_HOME/perl/lib/5.32.0:$ORACLE_HOME/perl/lib/site_perl/5.32.0:$ORACLE_HOME/appsutil/perl

# If logical hostname is passed in, call txkSyncDBConfig.pl with the
# -logicalhostname parameter, else call it without this parameter.
if [ "${LOGICAL_HOSTNAME}" == "" ];
then
# Call the EBS script txkSyncDBConfig.pl
LogMsg "Running txkSyncDBConfig.pl to configure with physical hostname."
{ echo "$APPS_SECRET"; } | perl $ORACLE_HOME/appsutil/bin/txkSyncDBConfig.pl \
-dboraclehome=$ORACLE_HOME \
-outdir=$ORACLE_HOME/appsutil/log \
-cdbsid=${ORACLE_SID} \
-pdbname=${PDB_NAME} \
-dbuniquename=${DB_UNIQUE_NAME} \
-israc=YES \
-virtualhostname=${VIRTUAL_HOSTNAME} \
-scanhostname=${SCAN_NAME} \
-scanport=${SCAN_LISTENER_PORT} \
-dbport=${DB_LISTENER_PORT} \
-appsuser=${APPS_USERNAME} | tee -a ${LOG_OUT}
else
LogMsg "Running txkSyncDBConfig.pl to configure with logical hostname."
{ echo "$APPS_SECRET"; } | perl $ORACLE_HOME/appsutil/bin/txkSyncDBConfig.pl \
-dboraclehome=$ORACLE_HOME \
-outdir=$ORACLE_HOME/appsutil/log \
-cdbsid=${ORACLE_SID} \
-pdbname=${PDB_NAME} \
-dbuniquename=${DB_UNIQUE_NAME} \
-israc=YES \
-virtualhostname=${VIRTUAL_HOSTNAME} \
-logicalhostname=${LOGICAL_HOSTNAME} \
-scanhostname=${SCAN_NAME} \
-scanport=${SCAN_LISTENER_PORT} \
-dbport=${DB_LISTENER_PORT} \
-appsuser=${APPS_USERNAME} | tee -a ${LOG_OUT}
fi

if [ $? -ne 0 ]; then
LogMsg "txkSynDBConfig.pl returned an error"
exit 1
fi
LogMsg "Running txkCfgUtlfileDir.pl with mode=setUtlFileDir"

{ echo "$APPS_SECRET"; echo "$DB_SECRET"; } | perl $ORACLE_HOME/appsutil/bin/txkCfgUtlfileDir.pl
-contextfile=$CONTEXT_FILE \
-oraclehome=$ORACLE_HOME \
-outdir=$ORACLE_HOME/appsutil/log \
-mode=setUtlFileDir \
-servicetype=opc | tee -a ${LOG_OUT}
if [ $? -ne 0 ]; then
LogMsg "txkCfgUtlfileDir.pl mode setUtlFileDir returned an error"
exit 1
fi

LogMsg "Running txkCfgUtlfileDir.pl with mode=syncUtlFileDir"

{ echo "$APPS_SECRET"; } | perl $ORACLE_HOME/appsutil/bin/txkCfgUtlfileDir.pl \
-contextfile=$CONTEXT_FILE \
-oraclehome=$ORACLE_HOME \
-outdir=$ORACLE_HOME/appsutil/log \
-mode=syncUtlFileDir \
-servicetype=opc | tee -a ${LOG_OUT}
if [ $? -ne 0 ]; then
LogMsg "txkCfgUtlfileDir.pl mode syncUtlFileDir returned an error"
exit 1
fi

LogMsg "Completed ReConfig - Database Home Reconfiguration"
}

90 changes: 90 additions & 0 deletions apps-unlimited/EBSR12.2onOCI/AppTier/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Oracle E-Business Suite Maximum Availability Architecture Disaster Recovery Scripts

Version 1.0

Copyright (c) 2025 Oracle and/or its affiliates.

Released under the Universal Permissive License v1.0 as shown at
<https://oss.oracle.com/licenses/upl/>.

The scripts provided here are a potential starting point for implementing full-stack automation of disaster recovery site switchover, failover, and middle tier file synchronization for Oracle E-Business Suite (EBS) R12.2 that have their database deployed on Oracle Exadata database machines in Oracle Cloud Infrastructure (OCI). They are examples. They are not part of any Oracle product, nor are they under any warranty. They are intended for customers to learn from and perhaps modify for their deployment.

See the overall README for these scripts, in the parent directory, EBSR12.2onOCI.

## Overview

The automation scripts for the application tier start and stop EBS application services and manage replication of the application file systems for different scenarios – normal operations at the primary, switching the standby to primary, and using the standby for snapshot standby testing.

The scripts should be placed in a common location at each site, one that each application tier compute instance at that site can access. As on the database servers, this directory is referenced as $SCRIPT_DIR. We recommend - and assume - adding the script directory to the administrator account’s PATH.

As with the database scripts, these scripts are written in Korn shell (ksh), use common routines / standard functions, and spawn SQL*Plus in a coroutine if needed, so that only one database connection is started.


## Using the EBS MAA DR Scripts

Please refer to the following solution playbooks for details about the Oracle E-Business Suite (EBS) topology, setup, and how to use these scripts:

* [Learn about maximum availability architecture for Oracle E-Business Suite](https://docs.oracle.com/en/solutions/learn-about-maa-for-ebs/index.html)

* [Provision and deploy a Maximum Availability Architecture solution for Oracle E-Business Suite on Oracle Cloud Infrastructure](https://docs.oracle.com/en/solutions/deploy-maa-for-ebs-on-oci/index.html)

The scripts should be placed in a common location at each site - one that all application and middle tier compute instances can access. In this project, we created the following directory location on each site’s shared file system, and labeled it $SCRIPT_DIR in our .env file:
/u02/app/ebs/custom_admin_scripts/VISPRD

ALWAYS test scripts thoroughly on a test environment before promoting them to a production environment.

> [!IMPORTANT]
> Verify that you have completed all the prerequisites listed in the playbooks referenced above before testing these scripts.


## Scripts Managing the Application

The scripts for starting and stopping the application with awareness of switchover, failover, and operating as a snapshot standby for testing purposes

| Script | Content |
| ------ | ------ |
| ebsAppTier.env | Configuration details for middle tier scripts, so the scripts themselves are kept generic |
| web_entry_test.env | Parameters for web entry points when using standby for snapshot standby testing |
| web_entry_prod.env | Parameters for production web entry points, if they differ at the two sites |
| stdfuncs.sh | A set of standard functions – generic routines that are useful when scripting Linux, database, and EBS administrative tasks – to include in calling scripts on both the database and the application tier. Using these common functions simplifies each working script, making the code easier to write and maintain. As this file is simply a set of common routines , it does not start with a shebang. The calling script must have #!ksh as its first line for these routines to work properly.|
| startEBS.sh | This script combines the tasks needed to start EBS for three scenarios – normal operations, at the standby site for testing purposes, and as the final part of a switchover from the primary to the standby site for production operations. |
| stopEBS.sh | Stop EBS and middle tier services, either as a normal shutdown or as part of a switchover to a standby site |


## Scripts Managing File System Replication

Data Guard manages replication of data stored in the database from the primary site to the standby. Certain file systems also need to be replicated – the application and middle tier software, and the file-based output generated by the application programs. The software directories do not change frequently but do need to be kept in sync across the sites when the source is patched. The file-based output holds batch processing logs, report output, and interface files that have been generated for other systems outside the EBS database. These files need to be as close to in sync with the data inside the database as feasible, to ease the task of resolving differences between the state of data in the database and these flat files on failover.

The rsync script in this section replicates specific file system directories from the primary to the standby. The core synchronization script addresses these basic requirements:
* Regularly synchronize the file systems holding the relatively unchanging application and middle tier software to the standby
* Aggressively synchronize the file systems holding runtime output, keeping them as up to date as possible at the standby
* Avoid replicating instance-specific configuration data
* Allow file system replication to continue while using the standby for snapshot standby testing
* Multi-thread the data transfers so that they complete in a reasonable amount of time

The rsync direction is managed through site role transitions. The scripts are deployed at each region/site and are designed to always be running at each site as a cron job. The script's behavior depends on whether the rsync process is enabled or disabled and whether the site's database is in the PRIMARY or STANDBY role. These scripts respond to database role transitions and automatically change the direction of the replication.

We recommend the actual rsync script be run on a dedicated pair of compute instances, one at each site, so that snapshot standby testing at the DR site can take place without disrupting replication of production changes to the standby file system.

Example CRON job entries for the rsync scripts:

SCRIPT_DIR=/u02/app/ebs/custom_admin_scripts/VISPRD
*/5 * * * * applmgr $SCRIPT_DIR/syncEBS.sh $SCRIPT_DIR/fastFiles.env
0 1 * * * applmgr $SCRIPT_DIR/syncEBS.sh $SCRIPT_DIR/slowFiles.env

Note: These scripts are built with the assumption that the EBS application tiers are deployed on shared file systems in OCI. We used OCI’s File System Service (FSS).

| File | Content |
| ------ | ------ |
| stdfuncs.sh | This is the same file as described above, in Managing the Application |
| ebsAppTier.env | This is the same file as described above, in Managing the Application |
| ebsRsync.env | Environment settings for rsync scripts. They need database access and the ability to connect to the remote app tiers |
| slowFiles.env | Pointers to the files detailing directories to copy and files to exclude from those directories, and the files to copy in addition to those in the directories, for files and directories that DO NOT change frequently |
| fastFiles.env | Pointers to the files detailing directories to copy and files to exclude from those directories, and the files to copy in addition to those in the directories, for files and directories that DO change frequently |
| staticDirectories.txt or dynamicDirectories.txt | Files holding one line per directory to be synchronized by either the "slow" (static) or "fast" (dynamic) synchronization runs |
| staticExcludeFiles.txt or dynamicExcludeFiles.txt | Files holding one line per file to be excluded from either the "slow" (static) or "fast" (dynamic) synchronization runs |
| staticIncludeFiles.txt or dynamicIncludeFiles.txt | Files holding one line per file to be added to either the "slow" (static) or "fast" (dynamic) synchronization runs |
| enable_ebs_rsync.sh | Set this site up to be the source for file system replication, and enable the processes |
| disable_ebs_rsync.sh | Disable the rsync process at this site. Must be done at the standby site. |
| syncEBS.sh | Multi-threaded file system synchronization driver. |
| killSsync.sh | Only used on switchover. Kill any currently-running rsync process so a new one can be started, to efficiently ensure the standby file system is up to date prior to activating the standby site. |
57 changes: 57 additions & 0 deletions apps-unlimited/EBSR12.2onOCI/AppTier/callReConfig.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/ksh
#############################################################################
# callReConfig.sh
#
# Copyright (c) 2025 Oracle and/or its affiliates
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
#
# Call the scripts to reconfigure EBS on the database RAC nodes on remote
# hosts.
#
# Requires user equivalency across all RAC nodes.
#
# This script establishes the environment, gets the apps password.
# then executes ReConfig on remote hosts. It's called remotely by
# EBS_DB_RoleChange.sh
#
# Rev:
# 06/18/2025 No hard-coding to find env files
# 08/29/2024 Created
#############################################################################

mypath=`pwd`

. $HOME/EBSCDB.env
. ${SCRIPT_DIR}/EBSCFG.env
HostName=$(hostname)

. ${CONTEXT_ENV_FILE}

# Include the standard functions routines
. ${SCRIPT_DIR}/stdfuncs.sh

# Include the common code for reconfiguring the path. This holds the
# code that is executed in this script for the DB nodes remote to the main
# driving script.
. ${SCRIPT_DIR}/ChangeHomePath.sh

EnvSetup
LOG_OUT=${LOG_DIR}/${HostName}_callReConfig_${TS}.log

LogMsg "callReConfig.sh: Started"

# Get the apps password - needs to be set before executing ReConfig
GetLogon $APPS_SECRET_NAME
APPS_SECRET=$LOGON

# Note: we are not executing sqlplus for anything in this script, so are
# not launching the coroutine. Side effect: for this script, we need
# to substitute HostName for DbName, which is used in LogMsg
# GetDbName
DbName=$HostName

# Finally - do the work:
ReConfig

LogMsg "callReConfig.sh: Completed."

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
REM
REM Name: crt_db_role_change_trigger.sql
REM
REM Copyright (c) 2025 Oracle and/or its affiliates
REM Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
REM
REM Purpose: This script creates the required table and role change trigger that will in tern submit a job to the database scheduler
REM that runs an external job. This job executes scripts on all RAC nodes to reconfigure EBS on the DB nodes if those
REM scripts determine if reconfiguration is required.
REM
REM The apps.xxx_EBS_role_change table is an EBS CEMLI only used by these scripts and the applicatin mid tiers. Because the
REM job runs on the first RAC node that transitions the database to the PRIMARY role and, that the job is asyncronous (but will
REM run immediately once submitted, we need to insert a row per each RAC node into this table so that as each set of scripts
REM complete to completion on each RAC node, they will delete the row corrosponding to their node name. The scripts that
REM start application services will check for rows in this table. When the row count is zero, they then will start application
REM services.
REM NOTE: This table will not be managed by ADOP nor undergo any edition redefinition changes.

set echo on

alter session set container = VISPRD;

drop table apps.xxx_EBS_role_change;

create table apps.xxx_EBS_role_change (
host_name varchar2(128),
rolechange_date date
);

REM Role change database trigger must be defined at the CDB level.

alter session set container = CDB$ROOT;

CREATE OR REPLACE TRIGGER Configure_EBS_AfterRoleChange AFTER db_role_change ON DATABASE
DECLARE
v_role VARCHAR(30);
BEGIN

SELECT DATABASE_ROLE INTO v_role FROM V$DATABASE;

IF v_role = 'PRIMARY' THEN

-- Submit the job that will execute the external scripts. The job will run immediately.
DBMS_SCHEDULER.CREATE_JOB (
Job_name=> 'EBS_DB_RoleChange',
Job_type=> 'EXECUTABLE',
Job_action => '/home/oracle/ebscdb/custom_admin_scripts/EBS_DB_RoleChange.sh',
Enabled => TRUE
);
DBMS_SCHEDULER.ENABLE('EBS_DB_RoleChange');

END IF;
END;
/

alter trigger Configure_EBS_AfterRoleChange enable;


49 changes: 49 additions & 0 deletions apps-unlimited/EBSR12.2onOCI/AppTier/disable_ebs_rsync.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/sh
############################################################################
# File name: disable_ebs_rsync.sh
#
# Copyright (c) 2025 Oracle and/or its affiliates
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
#
# Description: Create the *_rsync_disabled file, showing file system
# replication is not active at this site. This must be set
# at the standby site.
#
# Usage: disable_ebs_rsync.sh <fully qualified name of run env file>
# Can be called directly, but is called by stopEBS.sh
#
# Errors: No run environment file specified
# Cannot find run environment file
#
# Revisions:
# Date What
# 7/1/2023 Created
############################################################################

. ./ebsRsync.env

if [ $# -eq 0 ]
then
echo "No run environment file supplied. Please provide a run env file."
echo "Usage: disable_ebs_rsync.sh <run env file>"
echo "Example: disable_ebs_rsync.sh fastFiles.env"
exit 1
fi

if [ ! -f "$1" ]
then
echo "File $1 does not exist."
exit 1
fi

source $1

if [ -f "${SCRIPT_DIR}/.${fsAlias}_rsync_disabled" ]
then
echo "EBS rsync job for ${fsAlias} already disabled."
else
touch ${SCRIPT_DIR}/.${fsAlias}_rsync_disabled
echo "EBS rsync job for ${fsAlias} disabled."
fi


Loading