The first step in providing GemStone/S 64 Bit as a Cloud Foundry service is having it installed with Cloud Foundry. The new “experimental” vcap_dev_setup script uses Chef to install various components and we will install GemStone/S this way in our private cloud (created here). These steps will all take place in a shell on the server.
Edit ~/cloudfoundry/vcap/dev_setup/lib/job_manager.rb to add “gemstone” to the list of services in line 19.
SERVICES = ["gemstone", "redis", "mysql", "mongodb", "neo4j"]
Create ~/cloudfoundry/vcap/dev_setup/roles/gemstone_gateway.json with the following:
{ "name": "gemstone_gateway", "override_attributes": {}, "json_class": "Chef::Role", "description": "GemStone/S services gateway", "chef_type": "role", "run_list" : ["recipe[deployment]", "recipe[essentials]", "recipe[ruby]", "recipe[gemstone::gateway]"] }
Create ~/cloudfoundry/vcap/dev_setup/roles/gemstone_node.json with the following:
{ "name": "gemstone", "override_attributes": {}, "json_class": "Chef::Role", "description": "GemStone/S database for apps", "chef_type": "role", "run_list" : ["recipe[deployment]", "recipe[essentials]", "recipe[ruby]", "recipe[gemstone]", "recipe[gemstone::node]"] }
We will create the following directories and files:
- ~/cloudfoundry/vcap/dev_setup/cookbooks/gemstone/
- attributes/
- default.rb
- recipes/
- default.rb
- gateway.rb
- node.rb
- templates/
- default/
- datacurator.tpz.erb
- gemstone_gateway.yml.erb
- gemstone_node.yml.erb
- gs64stone.conf.erb
- gslist.erb
- reset_passwords.tpz.erb
- startstone.erb
- stopstone.erb
- topaz.conf.erb
- topaz_dc.erb
- topaz.erb
- .topazini.erb
- default/
- attributes/
Create the Chef cookbook directories:
mkdir ~/cloudfoundry/vcap/dev_setup/cookbooks/gemstone/ cd ~/cloudfoundry/vcap/dev_setup/cookbooks/gemstone/ mkdir attributes recipes templates templates/default
Create attributes/default.rb with the following (with changes to the last line to give a good password):
default[:gemstone][:version] = "3.0.1" default[:gemstone][:gs64ldi] = "50377" default[:gemstone][:path] = File.join(node[:deployment][:home], "deploy", "gemstone") default[:gemstone][:service_dir] = "/var/vcap/services/gemstone" # the following provide a max of 512 MB (okay for a 1 GB machine) default[:gemstone][:shmmax] = "536870912" default[:gemstone][:shmall] = "131072"
default[:gemstone_node][:available_memory] = "4096" default[:gemstone_node][:index] = "0" default[:gemstone_node][:max_memory] = "128" default[:gemstone_node][:token] = "changegemstonetoken" default[:gemstone_node][:spc_size_kb] = "131072" default[:gemstone_node][:tempobj_cache_size] = "131072" default[:gemstone_node][:stonename] = "gs64stone" # generate a good replacement for the following # (e.g., http://www.random.org/passwords/) default[:gemstone_node][:password] = "swordfish"
Create recipes/default.rb with the following:
# # Cookbook Name:: gemstone # Recipe:: default # # Copyright 2012, VMware # # case node['platform'] when "ubuntu" gs64ldi = node[:gemstone][:gs64ldi] bash "Add gs64ldi to /etc/services" do user "root" code <<-EOH echo "gs64ldi #{gs64ldi}/tcp # GemStone/S" >> /etc/services EOH not_if do string = `grep -w gs64ldi /etc/services | xargs echo | \ cut -d" " -f2 | cut -d"/" -f1`.strip !string.empty? && Integer(string) == Integer(gs64ldi) end end # # Shared Memory shmmax = node[:gemstone][:shmmax] shmall = node[:gemstone][:shmall] bash "Set kernel parameters for shared memory for GemStone/S 64 Bit" do user "root" code <<-EOH sysctl -w kernel.shmmax=#{shmmax} sysctl -w kernel.shamll=#{shmall} echo "kernel.shmmax = #{shmmax}" >> /etc/sysctl.conf echo "kernel.shmall = #{shmall}" >> /etc/sysctl.conf EOH not_if do Integer(shmmax) <= Integer(`sysctl kernel.shmmax | cut -d" " -f3`) end end # # Download product tree dir_name = "GemStone64Bit#{node[:gemstone][:version]}-x86_64.Linux" file_name = dir_name + ".zip" bash "Download GemStone/S 64 Bit" do cwd File.join("", "tmp") user node[:deployment][:user] code <<-EOH ftp -inv ftp.gemstone.com <<-FTP_END user anonymous swordfish cd /pub/GemStone64/#{node[:gemstone][:version]}/ binary get #{file_name} bye FTP_END EOH not_if do ::File.exists?(File.join("", "tmp", file_name)) end end # bash "Install GemStone/S 64 Bit" do user node[:deployment][:user] group node[:deployment][:user] cwd File.join("", "tmp") code <<-EOH unzip -q #{file_name} -d #{node[:gemstone][:path]} ln -s #{node[:gemstone][:path] + "/" + dir_name} \ #{node[:gemstone][:path]}/product EOH not_if do ::File.exists?(File.join(node[:gemstone][:path], dir_name , \ "bin", "startstone")) end end # ["", "bin", "data", "etc", "locks", "log"].each do | dir | directory File.join(node[:gemstone][:service_dir], dir) do owner node[:deployment][:user] group node[:deployment][:user] mode "0755" end end # %w(gs64stone topaz).each do | name | template File.join(node[:gemstone][:service_dir], "etc","#{name}.conf") do source "#{name}.conf.erb" mode 0666 owner node[:deployment][:user] group node[:deployment][:user] end end # %w(startstone stopstone gslist).each do | name | template File.join(node[:gemstone][:service_dir], "bin", name) do source "#{name}.erb" mode 0500 owner node[:deployment][:user] group node[:deployment][:user] end end # %w(topaz).each do | name | template File.join(node[:gemstone][:service_dir], "bin", name) do source "#{name}.erb" mode 0555 owner node[:deployment][:user] group node[:deployment][:user] end end # template File.join(node[:gemstone][:service_dir], "bin", ".topazini") do source ".topazini.erb" mode 0444 owner node[:deployment][:user] group node[:deployment][:user] end # template File.join(node[:gemstone][:service_dir], "bin", "topaz_dc") do source "topaz_dc.erb" mode 0500 owner node[:deployment][:user] group node[:deployment][:user] end # %w(datacurator.tpz reset_passwords.tpz).each do | name | template File.join(node[:gemstone][:service_dir], "bin", name) do source "#{name}.erb" mode 0400 owner node[:deployment][:user] group node[:deployment][:user] end end # bash "Copy keyfile and extent" do user node[:deployment][:user] group node[:deployment][:user] cwd node[:gemstone][:service_dir] code <<-EOH cp #{node[:gemstone][:path]}/product/seaside/etc/gemstone.key etc cp #{node[:gemstone][:path]}/product/bin/extent0.dbf data chmod 644 data/extent0.dbf cp #{node[:gemstone][:path]}/product/data/system.conf etc EOH not_if do ::File.exists?(File.join(node[:gemstone][:service_dir], "data", \ "extent0.dbf")) end end # bash "Reset passwords" do user node[:deployment][:user] group node[:deployment][:user] cwd File.join(node[:gemstone][:service_dir], "bin") code <<-EOH ./startstone ./topaz < reset_passwords.tpz ./stopstone EOH not_if do ::File.exists?(File.join(node[:gemstone][:service_dir], "data", \ "tranlog1.dbf")) end end # else Chef::Log.error("Installation of GemStone/S 64 Bit not supported on this platform.") end
Create recipes/gateway.rb with the following:
# # Cookbook Name:: gateway # Recipe:: default # # Copyright 2012, VMware # cloudfoundry_service "gemstone" do components ["gemstone_gateway"] end
Create recipes/node.rb with the following:
# # Cookbook Name:: node # Recipe:: default # # Copyright 2012, VMware # cloudfoundry_service "gemstone" do components ["gemstone_node"] end
Create templates/default/datacurator.tpz.erb to login into Topaz as DataCurator:
level 1 iferr 1 stk iferr 2 stack iferr 3 exit set user DataCurator pass <%= node[:gemstone_node][:password] %> set gems <%= node[:gemstone_node][:stonename] %> login
Create templates/default/gemstone_gateway.yml.erb to configure the gateway:
--- cloud_controller_uri: <%= node[:cloud_controller][:service_api_uri] %> service: name: gemstone version: "3.0" description: 'GemStone/S 64 Bit database service' plans: ['free'] tags: ['gemstone', 'object'] host: localhost index: <%= node[:gemstone_node][:index] %> token: <%= node[:gemstone_node][:token] %> mbus: nats://<%= \ node[:nats_server][:user] %>:<%= \ node[:nats_server][:password] %>@<%= \ node[:nats_server][:host] %>:<%= \ node[:nats_server][:port] %>/ pid: /var/vcap/sys/run/gemstone_service.pid node_timeout: 2 logging: level: debug
Create templates/default/gemstone_node.yml.erb to configure the service node:
--- local_db: sqlite3:/var/vcap/services/gemstone/gemstone_node.db mbus: nats://<%= \ node[:nats_server][:user] %>:<%= \ node[:nats_server][:password] %>@<%= \ node[:nats_server][:host] %>:<%= \ node[:nats_server][:port] %>/ index: <%= node[:gemstone_node][:index] %> base_dir: /var/vcap/services/gemstone/ pid: /var/vcap/sys/run/gemstone_node.pid available_memory: <%= node[:gemstone_node][:available_memory] %> node_id: <%= "gemstone_node_#{node[:gemstone_node][:index]}" %> max_memory: <%= node[:gemstone_node][:max_memory] %> migration_nfs: /mnt/migration logging: level: debug
Create templates/default/gs64stone.conf.erb for the stone configuration file:
KEYFILE = <%= node[:gemstone][:service_dir] %>/etc/gemstone.key; DBF_EXTENT_NAMES = <%= node[:gemstone][:service_dir] %>/data/extent0.dbf; STN_TRAN_LOG_DIRECTORIES = <%= node[:gemstone][:service_dir] %>/data/, <%= node[:gemstone][:service_dir] %>/data/; STN_TRAN_LOG_SIZES = 100, 100; SHR_PAGE_CACHE_SIZE_KB = <%= node[:gemstone_node][:spc_size_kb] %>; STN_TRAN_FULL_LOGGING = TRUE;
Create templates/default/gslist.erb to list the GemStone/S processes:
#!/bin/bash export GEMSTONE=<%= node[:gemstone][:path] %>/product export PATH=$GEMSTONE/bin:$PATH export GEMSTONE_GLOBAL_DIR=<%= node[:gemstone][:service_dir] %> gslist -cvl
Create templates/default/reset_passwords.tpz.erb change the passwords for the build-in users as part of the install process:
set gems <%= node[:gemstone_node][:stonename] %> set user SystemUser pass swordfish login run (AllUsers userWithId: 'SystemUser') password: '<%= node[:gemstone_node][:password] %>'. (AllUsers userWithId: 'DataCurator') password: '<%= node[:gemstone_node][:password] %>'. (AllUsers userWithId: 'GcUser') password: '<%= node[:gemstone_node][:password] %>'. (AllUsers userWithId: 'SymbolUser') password: '<%= node[:gemstone_node][:password] %>'. (AllUsers userWithId: 'Nameless') password: '<%= node[:gemstone_node][:password] %>'. System commitTransaction % logout exit
Create templates/default/startstone.erb to start the GemStone/S database service:
#!/bin/bash export GEMSTONE=<%= node[:gemstone][:path] %>/product export PATH=$GEMSTONE/bin:$PATH export GEMSTONE_GLOBAL_DIR=<%= node[:gemstone][:service_dir] %> startstone -l <%= node[:gemstone][:service_dir] %>/log/gs64stone.log \ -e <%= node[:gemstone][:service_dir] %>/etc/gs64stone.conf \ -z <%= node[:gemstone][:service_dir] %>/etc/system.conf
Create templates/default/stopstone.erb to stop the GemStone/S database service:
#!/bin/bash export GEMSTONE=<%= node[:gemstone][:path] %>/product export PATH=$GEMSTONE/bin:$PATH export GEMSTONE_GLOBAL_DIR=<%= node[:gemstone][:service_dir] %> stopstone -i <%= node[:gemstone_node][:stonename] %> \ DataCurator <%= node[:gemstone_node][:password] %>
Create templates/default/topaz.conf.erb as a configuration file for the Topaz processes:
GEM_TEMPOBJ_CACHE_SIZE = <%= node[:gemstone_node][:tempobj_cache_size] %>;
Create templates/default/topaz_dc.erb to start a Topaz process as DataCurator:
#!/bin/bash export GEMSTONE=<%= node[:gemstone][:path] %>/product export PATH=$GEMSTONE/bin:$PATH export GEMSTONE_GLOBAL_DIR=<%= node[:gemstone][:service_dir] %> topaz -l \ -I <%= node[:gemstone][:service_dir] %>/bin/datacurator.tpz \ -e <%= node[:gemstone][:service_dir] %>/etc/topaz.conf \ -z <%= node[:gemstone][:service_dir] %>/etc/system.conf
Create templates/default/topaz.erb to start a non-DataCurator Topaz process:
#!/bin/bash export GEMSTONE=<%= node[:gemstone][:path] %>/product export PATH=$GEMSTONE/bin:$PATH export GEMSTONE_GLOBAL_DIR=<%= node[:gemstone][:service_dir] %> topaz -l \ -I <%= node[:gemstone][:service_dir] %>/bin/.topazini \ -e <%= node[:gemstone][:service_dir] %>/etc/topaz.conf \ -z <%= node[:gemstone][:service_dir] %>/etc/system.conf
Create templates/default/.topazini.erb to provide a general Topaz initialization:
level 1 iferr 1 stk iferr 2 stack iferr 3 exit set gems <%= node[:gemstone_node][:stonename] %>
When these files have been created, you can rerun the deployment script:
~/cloudfoundry/vcap/dev_setup/bin/vcap_dev_setup -d ~/cloudfoundry
This will download and install the GemStone/S product at ~/cloudfoundry/.deployments/devbox/deploy/gemstone/product. It will also create a place to hold the database at:
- /var/vcap/services/gemstone/
- bin/
- datacurator.tpz
- gslist
- reset_passwords.tpz
- startstone
- stopstone
- topaz
- topaz_dc
- .topazini
- data/
- extent0.dbf
- etc/
- gemstone.key
- gs64stone.conf
- system.conf
- topaz.conf
- locks/
- log/
- bin/
From the bin directory you can start the database and login as DataCurator and execute various Topaz commands.
Later we will look at presenting GemStone/S 64 Bit as a service in Cloud Foundry.
2 comments
Comments feed for this article
March 12, 2012 at 12:48 pm
Adding GemStone as a Service to Cloud Foundry « Programming Gems (on GemStone)
[…] our previous post we used Chef to install GemStone/S 64 Bit into Cloud Foundry. Now we add code so that GemStone is […]
March 13, 2012 at 6:23 pm
Adding Topaz as a Runtime in Cloud Foundry « Programming Gems (on GemStone)
[…] provided with GemStone/S, but it needs a couple fixes to work with Cloud Foundry. Our earlier post shows how to install GemStone/S and the Chef script installs the product tree at […]