<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=269747997384049&amp;ev=PageView&amp;noscript=1">

AVIO Insights

Cooking with Chef

Introduction

Prepping a server for an Oracle Fusion Middleware installation is comprised of a number of mundane, repetitive, somewhat time consuming and always inconsistently applied steps.  At AVIO we use the the Rubicon Red MyST tool for FMW provisioning.  There is no better configuration management tool for FMW platform provisioning.  Since MyST does all the hard stuff for us it seemed odd the server prep tasks weren't automated as well.  The key server prepping steps are listed below.

  • Creating the oracle user and group
  • Downloading and Installing a compatible Java
  • Setting up the oracle user's login
  • Creating System swap file that would be used by FMW installers
  • Downloading the FMW installation binaries.  

There are a number of configuration management tools like Chef, Puppet, Ansible that can perform these tasks quite easily.  In this case we needed a tool that could be easily installed and run in fewer steps than the current manual prepping steps take.

Chef from Chef

Chef comes in several flavors.  For mature configuration management scenarios there is the Chef Server tool that contains a fully distributed environment consisting of a Chef Developer client (DK) and the Chef Server that coordinates the configuration to the Chef target servers.   In my use case I was interested in a simpler setup, one that I could run one-time on a server and do it in the fewest possible steps.

For standalone use on a server there is Chef Solo, which provides a thin Chef client to implement standalone server configurations.  In this blog you will see there are just three steps to install and then execute the Chef recipes.   

Getting Started

  • In my case I was using Amazon Linux EC2 for the server instance and reference Amazon S3 in various wget recipes to pull down the requisite binaries.
  • Internet access on the server is needed or manually copy the Chef Solo installation.
  • SSH to the server with sudo access is required.  

Step 1: Install Chef Solo

The Chef Client installer could be downloaded and run (RPM install) or you may ssh into the server and run the following Omnitruck installer that will detect the OS, download and install the correct Chef package.

sudo curl -L https: //omnitruck.chef.io/install.sh | sudo bash

Step 2: Checkout the Chef Recipes from Source Control

Good Community of Chef Resources

Ideally, you should be storing the Chef configuration management recipes in a source repository. Chef is nicely integrated with GitHub and provides publicly available recipes that are nicely documented and integrated on the Chef website. I cloned the Git Chef recipes into an "aviochef" directory, in the ec2-user's home.

Illustrated aviochef Directory

The structure and contents of the aviochef Git directory is illustrated below. There are two files, listed at the end that Chef Solo cares about: solo.rb and node.json.  (The recipes are kept in the cookbooks/recipes directory and will be summarized at the conclusion of the blog.)

aviochef

+-- cookbooks

¦   +-- fmw_aws

¦   ¦   +-- attributes

¦   ¦   ¦   +-- default.rb

¦   ¦   +-- definitions

¦   ¦   +-- files

¦   ¦   +-- libraries

¦   ¦   +-- metadata.rb

¦   ¦   +-- providers

¦   ¦   +-- README.md

¦   ¦   +-- recipes

¦   ¦   ¦   +-- create_oracle.rb

¦   ¦   ¦   +-- default.rb

¦   ¦   ¦   +-- get_installers.rb

¦   ¦   ¦   +-- install_java.rb

¦   ¦   ¦   +-- update_bashrc.rb

¦   ¦   ¦   +-- yum_wget.rb

¦   ¦   +-- resources

¦   ¦   +-- templates

¦   ¦       +-- default

¦   ¦       +-- oracle_bashrc.erb

¦   +--

+-- node.json

+-- solo.rb

The Chef Solo Configuration File

The solo.rb file contains properties to identify where the Chef cookbooks are and a reference to the location of the file (node.json) with the Chef recipe run list.

file_cache_path '/home/ec2-user/aviochef'

cookbook_path '/home/ec2-user/aviochef/cookbooks'

json_attribs '/home/ec2-user/aviochef/node.json'

The Chef Solo Recipe Runlist

The node.json file shown below references the recipe runlist the Chef Solo requires.  

{

"run_list": [

    "recipe[fmw_aws::create_oracle]"

  , "recipe[fmw_aws::yum_wget]"

  , "recipe[fmw_aws::install_java]"

  , "recipe[fmw_aws::update_bashrc]"

  , "recipe[fmw_aws::create_swap]"

  , "recipe[fmw_aws::get_installers]"

  ]

}

Step 3: Run Chef Recipes 

Use the Chef Solo command to run the recipes contained in the runlist, as shown below and it's done.

sudo chef-solo -c ~/aviochef/solo.rb

Review Chef Recipes

As described on the preceding steps there were only three commands required to install Chef and run our cookbook recipes to provision the server.  What about the recipes?  The devil's in the details as they say, so let's take a quick look at the more interesting of the recipes.

create_oracle.rb

Ruby script first create an oracle user, providing the user command with details about then name, group, home directory and lastly the password.    

user node.default['fmwmain']['oracle_user'] do

  action :create

  username node.default['fmwmain']['oracle_user']

  gid node.default['fmwmain']['oracle_group']

  manage_home true

  home node.default['fmwmain']['oracle_user_home']

  shell '/bin/bash'

  password node.default['fmwmain']['oracle_password']

end

Chef Best Practice

The property values used in this command are derived from the attributes/default.rb file that consists of the following values.  By using this best practice then other Chef recipes can reference the same property values.

default['fmwmain']['oracle_user']            = 'oracle'

default['fmwmain']['oracle_group']          = 'oinstall'

default['fmwmain']['oracle_password']   ='$1$PLrT6HBF$O6cvMEfUGLPPm/xrAwNga0'

default['fmwmain']['oracle_user_home'] = '/home/oracle'

default['fmwmain']['oracle_home']          = '/opt/u01/oracle'

default['fmwmain']['oracle_software']     = '/opt/u01/oracle/software/12.2.1.1'

default['fmwmain']['oracle_java']            = '/opt/u01/oracle/software/java'

default['fmwmain']['java_root']                = '/opt/java'

default['fmwmain']['java_home']             = '/opt/java/jdk1.8.0_111'
 

install_java.rb

In this recipe various directories are created and then the Java installer is downloaded (in this case we use Amazon S3 to keep the binaries) using the remote_file command which performs a "wget" to the specified directory and file location.  Lastly, a bit of bash is run to extract Java into the Java home.  

directory node.default['fmwmain']['oracle_java'] do

  action :create

end
directory node.default['fmwmain']['java_root'] do

  action :create

end
java_software =node.default['fmwmain']['oracle_java'] +'/jdk-8u111-linux-x64.tar.gz'

tar_command='tar xzvf '+java_software
remote_file java_software do

  source 'https://s3-server/product-installers/oracle/java/jdk-8u111-linux-x64.tar.gz' 

  mode '0755'

  action :create

end
# run shell command to do tar extract

execute 'extract_java_tar' do

  command tar_command

  cwd node.default['fmwmain']['java_root']

  not_if { File.exists?(node.default['fmwmain']['java_home']) }

end

update_bash.rb

Chef Best Practice

When creating files for a configuration a Chef best practice is to use an "embedded" Ruby template.  This was done for the creation of the .bashrc file for the oracle user.  The reference to the template is on the "source" line below. The "variables" line passes the export_home and export_path variable to the template.  

bashrc_dir = node.default['fmwmain']['oracle_user_home'] + '/.bashrc'

export_home = 'export JAVA_HOME=' +node.default['fmwmain']['java_home']

export_path = 'export PATH=' +node.default['fmwmain']['java_home'] +'/bin'+':$PATH'
template bashrc_dir do

source "oracle_bashrc.erb"

variables({ :export_home => export_home, :export_path => export_path })

action :create

owner node.default['fmwmain']['oracle_user']

group node.default['fmwmain']['oracle_group']

mode '0755'

end

The template file (templates/oracle_bashrc.erb) contains references to the export_home and export_path variables, as shown on the last two lines of the file.

# .bashrc
# # Source global definitions

if [ -f /etc/bashrc ]; then

  . /etc/bashrc

fi
# User specific aliases and functions

<%= @export_home %>

<%= @export_path %>
 

Cleaning Up With Chef

Let's push the cooking metaphor to the limit and wrap things up with some kitchen cleanup.   If you need to remove the aforementioned server prep then run the remove_oracle.rb Chef recipe shown below.  

remove_oracle.rb

# recipe will remove the oracle user/group and (most) directories created by create_oracle recipe

user node.default['fmwmain']['oracle_user'] do

  action :remove

  username node.default['fmwmain']['oracle_user']

  ignore_failure true

end
group node.default['fmwmain']['oracle_group'] do

  action :remove

  ignore_failure true

end
directory node.default['fmwmain']['oracle_user_home'] do

  owner node.default['fmwmain']['oracle_user']

  action :delete

  recursive true

end
directory '/opt/java' do

  action :delete

  recursive true

end
#Uses swap cookbook method

swap_file '/swapfile' do

  action :remove

  ignore_failure true

  only_if { File.exists?("/swapfile")}

end

Chef Worked Out Nicely

The Chef tool proved to be easy to install, configure and run.  Between Chef and MyST it provides full automation all of the tasks associated with Fusion Middleware provisioning.  While shell scripting may have been an alternative, using Chef provide a Ruby programming syntax and a large community of Chef recipes to draw upon should the need arise for more complicated configuration. The full scripts are available on request.

 

4 minute read