Wednesday, November 27, 2013

Re-wire Oracle SOA Datasource to use Active GridLink for RAC

Starting 11gR1 PS5 (11.1.1.6), Oracle SOA Suite platform is enhanced to support Active GridLink for Real Application Clusters (RAC).

WebLogic Server Active GridLink (AGL) for RAC provides the best available support for the RAC features in Oracle Database 11g. The generic data source is the implementation for single database access. The Multi-data source is the native WebLogic middle tier implementation for RAC integration, which does not leverage Oracle Notification Service (ONS).

The GridLink data source is the new Active GridLink implementation and includes the features of generic data sources, taking advantage of Oracle RAC supporting Fast Connection Failover (FCF), Runtime Connection Load-Balancing (RCLB), and XA Affinities. A GridLink data source is created for JDBC connectivity between WebLogic Server and a service targeted to an Oracle RAC cluster. It uses the Oracle Notification Service (ONS) to adaptively respond to state changes in an Oracle RAC instance.

Here are couple of good resources that can help you understand the AGL concepts in more detail:
- What is Active GridLink
- Benefits of AGL data sources

Basically, a data source configuration is always an Active GridLink (AGL) data source configuration if FanEnabled=true or the OnsNodeList is non-null.

Here is a modified version of a python script (borrowed from my colleague), that you can use to rewire the SOA data sources to use Active GridLink for RAC databases. Before executing the script, remember to shutdown all the WLS SOA domain servers; its an offline wlst script.


#
# The script must be executed in WLST offline mode. Restart the ADMIN SERVER
# post script execution for the changes to take effect.
#
#-------------------------------------------------------------------------------
# Purpose: Sample Python Script to rewire SOA Suite 11g PS6 JDBC data sources
# to use Active GridLink for RAC
#
# Usage : soa-agl-ds-rewire.py <domain_path>
#
#-----------------------------------------------------------------------------
import os
import sys
#===========================================================================
# List of SOA/OSB Datasources and JDBC drivers
#===========================================================================
soaDS_list = \
{
'OraSDPMDataSource':(4,'D','ORASDPM'),
'SOADataSource':(4,'X','SOAINFRA'),
'EDNDataSource':(4,'X','SOAINFRA'),
'EDNLocalTxDataSource':(4,'D','SOAINFRA'),
'SOALocalTxDataSource':(4,'D','SOAINFRA'),
'wlsbjmsrpDataSource':(2,'X','SOAINFRA'),
'mds-soa':(5,'D','MDS'),
'mds-owsm':(15,'D','MDS')
}
jdbcDrv = \
{
'D':'oracle.jdbc.OracleDriver',
'X':'oracle.jdbc.xa.client.OracleXADataSource'
}
#==========================================================================
# Function to configure WLS JDBC data source to use Active GridLink for RAC
#==========================================================================
def rewire_DS(ds, prefix, service,\
listeners, dbsch_pwd,\
protocol, ons_list = None) :
print("Configuring %s:" % ds)
drvt = soaDS_list[ds][1]
drv = jdbcDrv[drvt]
if ons_list is None:
url = 'jdbc:oracle:thin:@'+listeners[0]+'/'+service
else:
### RAC Gridlink config -- can either use SCAN hosts (ons_list) or all listeners
url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST="
for lsn in listeners:
host_port = lsn.split(':')
host = host_port[0]
port = host_port[1]
url = url + "(ADDRESS=(PROTOCOL=%s)(HOST=%s)(PORT=%s))" % (protocol,host,port)
url = url + ")(CONNECT_DATA=(SERVICE_NAME=%s)))" % service
try:
user = "%s_%s" % (prefix, soaDS_list[ds][2])
cd('/JDBCSystemResource/'+ds+'/JdbcResource/'+ds)
cd('JDBCDriverParams/NO_NAME_0')
set('URL',url)
set('DriverName',drv)
cd('/JDBCConnectionPool/'+ds)
set('Password',dbsch_pwd)
cd('/JDBCSystemResource/'+ds+'/JdbcResource/'+ds+'/JDBCDriverParams/NO_NAME_0/Properties/NO_NAME_0/Property')
cd('user')
set('Value',user)
if ons_list :
onsl = (str(ons_list).strip("[]")).replace("'","").replace(" ","")
cd('/JDBCSystemResource/'+ds+'/JdbcResource/'+ds)
try:
cd('JDBCOracleParams/NO_NAME_0')
set('FanEnabled','true')
set('OnsNodeList',onsl)
except:
pprint("Creating Gridlink DS")
cd('/JDBCSystemResource/'+ds+'/JdbcResource/'+ds)
create('JDBCOracleParams','JDBCOracleParams')
cd('JDBCOracleParams/NO_NAME_0')
set('FanEnabled','true')
set('OnsNodeList',onsl)
pprint("Gridlink for %s set to use ONS: %s" % (ds,onsl))
else :
gridl = False
try:
#Check for previous Gridlink Setup
cd('JDBCOracleParams/NO_NAME_0')
gridl = True
except:
print "No Gridlink found"
if(gridl):
set('FanEnabled','false')
set('OnsNodeList','')
pprint("DataSource %s has been configured." % ds)
except:
dumpStack()
########################################################################
# MAIN
########################################################################
wlsDomainHome= " "
# prefix used by the SOA schemas for e.g. TEST_SOAINFRA
schema_prefix= "TEST"
# SOA database service name
service_name= "orcl"
# comma separated list of database listener host:port values; specify atleast one
listeners= "DBHOST:1521"
# ONS_List is used for RAC db only; can be left 'empty' otherwise
# e.g. for RAC - DBHOST-NODE1:6200,DBHOST-NODE2:6200
ons_list=
# protocol 'TCP' or 'SDP' for Exadata
protocol= "TCP"
# for simplicity, we will assume all SOA schema passwords are set to the same value;
# ideally the passwords must be prompted during script execution
soa_sch_passwd= "welcome1"
try:
wlsDomainHome = sys.argv[1]
except:
print 'WARNING:Not all command line parameters specified'
if (wlsDomainHome == " "):
sys.exit()
# read Domain
try:
readDomain(wlsDomainHome)
print '***** Read Domain: %s' % wlsDomainHome
except :
print 'XXXXX Could not Read Domain: %s' % wlsDomainHome
exit()
try:
### Rewire SOA DataSources to use Active GridLink
pprint("\n Begin DataSource Re-wiring")
for ds in soaDS_list:
try:
rewire_DS(ds, schema_prefix, service, listeners, soa_sch_passwd, protocol, ons_list)
except:
pprint("Configuring DataSource %s failed." % ds)
print 'Updating and Closing Domain'
updateDomain()
closeDomain()
except Exception, detail:
print 'FINAL Exception:', detail
dumpStack()
exit()