Multiple PS_CFG_HOMEs with the DPK

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.

4 thoughts on “Multiple PS_CFG_HOMEs with the DPK

  1. Hi Dan,

    Thanks for this.

    Does your app server, web server and process scheduler in each of your PS_CFG_HOMEs point to the same database?

    I’m hoping to use the DPK to configure a single machine with two PS_CFG_HOMEs that each host its own web/app/process scheduler) for two separate PeopleSoft databases. Have you managed to achieve this?

    Regards,

    Jay

    1. Hi Dan,

      You can ignore my previous comment. Using your PS_CFG_HOME fixes above, I’ve configured (to some degree of success) a single machine to host a midtier-only setup consisting of web, app and process scheduler servers for two separate MSSQL databases. I had a few issues getting this to work, and in the end modified the site.pp file to use a custom role with only the following pt_profiles: pt_tools_deployment, pt_psft_environment, pt_appserver.pp, pt_prcs and pt_pia.
      I also commented out a few things that were causing errors for me (e.g. calls to ::Pt_setup::Mssql_connectivity in pt_appserver.pp, pt_pia.pp and pt_prcs.pp files under puppet\etc\modules\pt_profile\manifests).

      Thanks for the post – it will be useful when we start deploying PT 8.55 on our new servers later this year.

      Jay

      1. HI Jay – glad you got it working. That sounds similar to our solution. It would be nice if we had more control over the Profile without having to comment/modify code. You can tell that the DPK was build with PeopleSoft Images in mind; the Profiles assume you want everything installed and Roles assume you want the configuration run every time.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax