Multiple PS_CFG_HOMEs with the DPK
Aug 10, 2016Dan Iverson
One of my biggest criticisms of the DPK is that it doesn’t support multiple PS_CFG_HOME’s for app server and process scheduler domains. This has been the biggest roadblock for me as I attempt to use the DPK to deploy an 8.55 infrasturcture. Currently (as of 8.55.08), all Tuxedo domains are created under a single folder.
Tuxedo expects the PS_CFG_HOME
environment variables to be set to know where to create domains. If you don’t set PS_CFG_HOME
, Tuxedo’s default setting will create the domains under %USER%\psft\pt\8.xx
.
With the DPK, there are parameters to set PS_CFG_HOME
environment variable at the app server, process scheduler, and web server sections in psft_customizations.yaml
. Use the ps_config_home:
value to populate the value for all domains. Or, you can set different values for each domain using the ps_cfg_home_dir:
inside the appserver_domain_list
, prcs_domain_list
, and pia_domain_list
section.
When the DPK runs, it takes these values and sets up environment variables. If you have more than one PS_CFG_HOME
specified for Tuxedo domains, the current DPK will only set environment variables once. The last PS_CFG_HOME
specified will be the environment variable value when Tuxedo domains are created.
This is why the DPK only uses 1 PS_CFG_HOME
for all Tuxedo domains; it doesn’t manage environment variables properly.
Setting PS_CFG_HOME
for Every Domain
To fix this, we need to set the PS_CFG_HOME
environment variable each time a Tuxedo domain is created (or booted). Puppet Providers handle the comamnd line calls to Tuxedo and setup programs. So a code change in the provider for Tuxedo domains where we need to make our change.
The Puppet Providers for Tuxedo are located under puppet\etc\modules\pt_config\lib\puppet\provider\
. In the providers, when a command line command is built, a function execute_command()
is used to handle the OS-level command line calls. Unfortunately, only the app server provider uses this function, because execute_command()
takes two parameters: command
and env
. The env
parameter lets us set environment variables for the command’s environment. Instead, we’ll use the Ruby syntaxt ENV[]
set an environment variable before the command is executed.
App Servers
There are two base files for app server domains: psftdomain.rb
and psftdomainboot.rb
. They are parents objects to the pt_app_domain\app_domain.rb
provider. The changes for application server domains can be made in the two parent files.
We’ll insert this code block before each command line call:
# PS_CFG_HOME Fix Begin
if Facter.value(:osfamily) == 'windows'
ps_cfg_home_dir_norm = resource[:ps_cfg_home_dir].gsub('/', '\\')
else
ps_cfg_home_dir_norm = resource[:ps_cfg_home_dir]
end
ENV['PS_CFG_HOME'] = ps_cfg_home_dir_norm
Puppet.notice(" PS_CFG_HOME=#{ps_cfg_home_dir_norm}")
# PS_CFG_HOME Fix End
In psftdomain.rb
, we’ll insert the code in the create()
method before the begin
code block:
def create pre_create()
domain_name = resource[:domain_name]
domain_type = get_domain_type()
template_type = get_template_type()
Puppet.debug("Creating domain: #{domain_name}")
Puppet.debug(" with attributes #{resource.to_hash.inspect}")
# PS_CFG_HOME Fix Begin
if Facter.value(:osfamily) == 'windows'
ps_cfg_home_dir_norm = resource[:ps_cfg_home_dir].gsub('/', '\\')
else
ps_cfg_home_dir_norm = resource[:ps_cfg_home_dir]
end
ENV['PS_CFG_HOME'] = ps_cfg_home_dir_norm
Puppet.notice(" PS_CFG_HOME=#{ps_cfg_home_dir_norm}")
# PS_CFG_HOME Fix End
begin
psadmin_cmd = File.join(resource[:ps_home_dir], 'appserv', 'psadmin')
if Facter.value(:osfamily) == 'windows'
command = "#{psadmin_cmd} #{domain_type} create -d #{domain_name} #{template_type} #{get_startup_settings} #{get_env_settings}"
execute_command(command)
else
domain_cmd('-m', '-s', '/bin/bash', '-l', resource[:os_user], '-c',
"#{psadmin_cmd} #{domain_type} create -d #{domain_name} " +
"#{template_type} #{get_startup_settings} #{get_env_settings}")
end
rescue Puppet::ExecutionFailure => e
raise Puppet::Error,
"Unable to create domain #{domain_name}: #{e.message}"
end
post_create()
@property_hash[:ensure] = :present
end
In psftdomainboot.rb
, we’ll insert the code block in the execute_psadmin_action()
method before the begin
code block:
def execute_psadmin_action(action)
domain_name = resource[:domain_name] domain_type = get_domain_type()
Puppet.debug("Performing action #{action} on domain #{domain_name}")
# PS_CFG_HOME Fix Begin
if Facter.value(:osfamily) == 'windows'
ps_cfg_home_dir_norm = resource[:ps_cfg_home_dir].gsub('/', '\\')
else
ps_cfg_home_dir_norm = resource[:ps_cfg_home_dir]
end
ENV['PS_CFG_HOME'] = ps_cfg_home_dir_norm
Puppet.notice(" PS_CFG_HOME=#{ps_cfg_home_dir_norm}")
# PS_CFG_HOME Fix End
begin
psadmin_cmd = File.join(resource[:ps_home_dir], 'appserv', 'psadmin')
if Facter.value(:osfamily) == 'windows'
db_type = get_db_type()
if db_type == 'ORACLE'
set_user_env()
end
command = "#{psadmin_cmd} #{domain_type} #{action} -d #{domain_name}"
command_output = execute_command(command)
else
os_user = resource[:os_user]
if os_user_exists?(os_user) == false
command_output="ERROR: os user #{os_user} does not exists"
else
command_output = domain_cmd('-m', '-s', '/bin/bash', '-', os_user, '-c',
"#{psadmin_cmd} #{domain_type} #{action} " + "-d #{domain_name}")
end
end
return command_output
rescue Puppet::ExecutionFailure => e
raise Puppet::ExecutionFailure, "Unable to perform action #{action}: #{e.message}"
end
end
Process Schedulers
For process scheduler domains, we need to modify the pt_prcs_domain\prcs_domain.rb
provider file. We’ll insert the code block in the pre_create()
method.
def pre_create
super()
domain_name = resource[:domain_name]
cfg_home_dir = resource[:ps_cfg_home_dir]
# PS_CFG_HOME Fix Begin
if Facter.value(:osfamily) == 'windows'
ps_cfg_home_dir_norm = resource[:ps_cfg_home_dir].gsub('/', '\\')
else
ps_cfg_home_dir_norm = resource[:ps_cfg_home_dir]
end
ENV['PS_CFG_HOME'] = ps_cfg_home_dir_norm
Puppet.notice(" PS_CFG_HOME=#{ps_cfg_home_dir_norm}")
# PS_CFG_HOME Fix End
domain_dir = File.join(cfg_home_dir, 'appserv', 'prcs', domain_name)
if File.exist?(domain_dir)
Puppet.debug("Removing Process Scheduler domain directory: #{domain_dir}")
FileUtils.rm_rf(domain_dir)
end
end
Closing Thoughts
Fixing the limitation of one PS_CFG_HOME with the DPK was the last hurdle for me to start using the DPK for all of my environment builds. With the DPK, and some custom Puppet code to extend the DPK, we are working on automating our environment builds. I posted the code changes on GitHub if you want to get the fix from there.
I have an SR open for this issue, but I also have an Idea on the Oracle Community site. If you would like to see this change incorporated into the delivered DPK, go vote for the idea.
Note: This was originally posted by Dan Iverson and has been transferred from a previous platform. There may be missing comments, style issues, and possibly broken links. If you have questions or comments, please contact [email protected].