In our last post we walked through adding GemStone/S as a service in Cloud Foundry. With this, we could access GemStone/S from an application written in a runtime/framework recognized by Cloud Foundry. Now, we look at what it takes to have GemStone/S recognized as a runtime/framework (named ‘topaz’) so we can work directly in server Smalltalk.
Changes to VMC on the Client
First, we need to make changes on the client so that VMC recognizes topaz as a framework. This process is discussed in detail here and involves a couple small edits to lib/cli/frameworks.rb. Insert the following at line 9 (to the list of FRAMEWORKS):
'Topaz' => ['topaz', { :mem => '256M', :description => 'Topaz for GemStone/S'}],
Then we insert the following detection code staring at line 42 (after the Rails detection):
# Topaz on GemStone elsif File.exist?('main.tpz') return Framework.lookup('Topaz')
Changes to VCAP on the Server
First we navigate to the VCAP location and create some directories:
cd ~/cloudfoundry/vcap/ mkdir ./dev_setup/cookbooks/topaz mkdir ./dev_setup/cookbooks/topaz/recipes mkdir ./dev_setup/cookbooks/topaz/attributes mkdir ./staging/lib/vcap/staging/plugin/topaz
The template for the topaz script at dev_setup/cookbooks/gemstone/templates/default/topaz.erb that we created earlier needs a few changes and should be replaced with the following:
#!/bin/bash if [[ "$1" == "-v" ]]; then echo "<%= node[:gemstone][:version] %>" exit 0 fi 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 $*
Next we need to modify the provisioning script at services/gemstone/resources/provision.tpz.erb to remove the NoGsFile* privileges so that we can write to stdout from Smalltalk. File-level security can be enforced by Cloud Foundry by setting ‘secure: true‘ in dea/config/dea.yml and starting VCAP as root (e.g., with sudo).
Next we modify cloud_controller/app/models/app.rb lines 26, 27 to add topaz as a runtime and framework:
Runtimes = %w[topaz ruby18 ruby19 java node php erlangR14B02 python26] Frameworks = %w[topaz sinatra rails3 java_web spring grails node php otp_rebar lift wsgi django unknown]
Next we modify dev_setup/cookbooks/cloud_controller/attributes/default.rb to insert the following at line 10:
default[:cloud_controller][:staging][:topaz] = "topaz.yml"
Next we modify
dev_setup/cookbooks/cloud_controller/templates/default/cloud_controller.yml.erb to insert the following at line 110:
topaz: version: 3.0.1
Next we create dev_setup/cookbooks/cloud_controller/templates/default/topaz.yml.erb with the following:
--- name: "topaz" runtimes: - "topaz": version: "3.0.1" description: "Topaz" executable: "/var/vcap/services/gemstone/bin/topaz" default: true environment: detection: - "main.tpz"
Next we modify dev_setup/cookbooks/dea/attributes/default.rb to add “topaz” to line 3:
default[:dea][:runtimes] = ["topaz", "ruby18", "ruby19", "nodejs", "java", "erlang", "php"]
Next we modify dev_setup/cookbooks/dea/templates/default/dea.yml.erb to insert the following at line 46:
<% if node[:dea][:runtimes].include?("topaz") %> topaz: executable: <%= File.join(node[:topaz][:path]) %> version: 3.0.1 environment: <% end %>
Next we create dev_setup/cookbooks/topaz/attributes/default.rb with the following:
include_attribute "deployment" default[:topaz][:version] = "3.0.1" default[:topaz][:path] = "/var/vcap/services/gemstone/bin/topaz"
Next we create dev_setup/cookbooks/topaz/recipes/default.rb with the following:
# # Cookbook Name:: topaz # Recipe:: default # # Copyright 2012, VMware # Chef::Log.debug("Topaz should have been installed with GemStone/S 64 Bit")
Next we create staging/lib/vcap/staging/plugin/manifests/topaz.yml with the following:
--- name: "topaz" runtimes: - topaz: version: '3.0.1' description: 'Topaz for GemStone/S' executable: /var/vcap/services/gemstone/bin/topaz default: true app_servers: detection: - "main.tpz": '.' staged_services:
Next we create staging/lib/vcap/staging/plugin/topaz/plugin.rb with the following:
class TopazPlugin < StagingPlugin include GemfileSupport def framework 'topaz' end # def stage_application Dir.chdir(destination_directory) do create_app_directories copy_source_files do_staging create_startup_script create_stop_script end end # def do_staging Dir.chdir("app") {|dir| # nothing really to do here! } end # def start_command "/var/vcap/services/gemstone/bin/topaz -I .topazini < main.tpz" end # private def startup_script vars = environment_hash # PWD here is the parent of the 'app' directory. generate_startup_script(vars) do cmds = [] cmds << 'USER=$(echo $VCAP_SERVICES | ' + \ 'grep -Po \'"user":.*?[^\\\\]",\' | cut -d\'"\' -f4)' cmds << 'PASS=$(echo $VCAP_SERVICES | ' + \ 'grep -Po \'"pass":.*?[^\\\\]",\' | cut -d\'"\' -f4)' cmds << 'HOST=$(echo $VCAP_SERVICES | ' + \ 'grep -Po \'"host":.*?[^\\\\]",\' | cut -d\'"\' -f4)' cmds << 'echo "set user $USER pass $PASS" > app/.topazini' cmds << 'echo "set gems !tcp@$HOST#server!gs64stone" >> app/.topazini' cmds << 'echo "login" >> app/.topazini' cmds.join("\n") end end # def stop_script vars = environment_hash generate_stop_script(vars) end # end
Next we create staging/lib/vcap/staging/plugin/topaz/staging with the following:
#!/usr/bin/env ruby require File.expand_path('../../common', __FILE__) plugin_class = StagingPlugin.load_plugin_for('topaz') plugin_class.validate_arguments! plugin_class.new(*ARGV).stage_application
Our demo application will be of WebTools, a “goodie” 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 ~/cloudfoundry/.deployments/devbox/deploy/gemstone/product/. The changes need to be made to examples/www/src/Server.gs (I would give the full path but it doesn’t display well with the blog formatting). In the #’doAnswer’ method we need to replace the #’lf’ message sends with #’crlf’ so that we get a CR/LF as required by the HTTP spec. In the #’handleRequest’ method we need to remove the check for HTTP/1.1 since Cloud Foundry sends the requests using a 1.0 format.
At this point we can deploy Cloud Foundry:
~/cloudfoundry/vcap/dev_setup/bin/vcap_dev_setup -d ~/cloudfoundry/
As we found earlier, this doesn’t properly install the staging code, so we copy it across manually:
fromDir=`find ~/cloudfoundry/vcap/staging/ | grep pip_support.rb` fromDir=`dirname $fromDir` toDir=`find ~/cloudfoundry/.deployments/devbox/ | grep pip_support.rb` toDir=`dirname $toDir` cp -r $fromDir/topaz $toDir cp $fromDir/manifests/topaz.yml $toDir/manifests/topaz.yml
We can now start Cloud Foundry, vcap start, and return to the client to create a new GemStone/S application.
Creating an Application
We need to have an application to push to the cloud, so we will start by creating a directory to hold the application on the client:
mkdir ~/cloud/topaz cd ~/cloud/topaz vim ~/cloud/topaz/main.tpz
Our application, main.tpz, will consist of the following Topaz script:
input $GEMSTONE/examples/www/install.tpz run | class port | class := GsSession currentSession userProfile symbolList last at: #'Server'. port := System gemEnvironmentVariable: 'VCAP_APP_PORT'. class new startForegroundServerAtPort: port asNumber. % logout exit
At this point we can push our application, give it a name, and bind it to a gemstone service:
Would you like to deploy from the current directory? [Yn]: Application Name: topaz-app Application Deployed URL [topaz-app.vcap.me]: Detected a Topaz for GemStone/S, is this correct? [Yn]: Memory reservation (128M, 256M, 512M, 1G, 2G) [256M]: How many instances? [1]: Would you like to bind any services to 'topaz-app'? [yN]: y The following system services are available 1: gemstone 2: mongodb 3: mysql 4: neo4j 5: redis Please select the one you wish to provision: 1 Specify the name of the service [gemstone-1b271]: Would you like to bind another service? [yN]: Would you like to save this configuration? [yN]: Creating Application: OK Creating Service [gemstone-1b271]: OK Binding Service [gemstone-1b271]: OK Uploading Application: Checking for available resources: OK Packing application: OK Uploading (0K): OK Push Status: OK Staging Application 'topaz-app': OK Starting Application 'topaz-app': OK
When the application has been started, we can navigate to http://topaz-app.vcap.me/ and see that we are interacting with a GemStone/S system over the web.
7 comments
Comments feed for this article
March 14, 2012 at 8:04 am
Andy Burnett
Sadly, the URL doesn’t seem to resolve to anything. Have you taken the service down?
March 14, 2012 at 8:20 am
James Foster
Hi Andy,
So far most of what we have been doing is working with a private cloud and one of the steps is to set up a tunnel between your client machine (localhost) and the private cloud. The domain vcap.me and all its subdomains are registered with the IP address 127.0.0.1, so is the same as localhost. This is why you can’t get to my private cloud (actually an Ubuntu virtual machine running on my MacBook Pro under Fusion).
Making GemStone/S available as a public cloud is another project, though there would be a significant difference between a technical proof-of-concept and a business proposition.
-James
March 14, 2012 at 8:29 am
Andy Burnett
Thanks James, sorry that I had completely misunderstood the context!
I am very excited about the possibility of a cloud based Gemstone, and I was obviously getting ahead of myself 😉
Cheers
Andy
March 14, 2012 at 8:40 am
James Foster
Any chance you can come to Biloxi next week? You might be interested in my presentation (http://www.stic.st/conferences/stic12/stic12-abstracts/smalltalk-in-the-cloud/).
March 14, 2012 at 9:02 am
Andy Burnett
Sadly not. Is it going to be video recorded? Alternatively, after the event, will you be posting your slides?
March 14, 2012 at 9:10 am
James Foster
I’m not sure of all the technical arrangements, but we will certainly try to get the word out.
March 20, 2012 at 8:52 pm
Topaz script for Cloud Foundry « Programming Gems (on GemStone)
[…] an earlier post we described a simple Topaz application that could be pushed to Cloud Foundry. It turns out that […]