In my previous post I described the process of build a private cloud using the “experimental” script provide on github. Part of the reason for using the newer script is that the older script is broken. Another reason is that the newer script seems to be the preferred direction. On the other hand, the new script creates a rather different environment from the old script, and most of the instructions and blog posts deal with the traditional environment. Because of this, I went back to the old setup and have been able to add a runtime and framework. This blog post will describe that effort (and a subsequent one will describe how to work in the new environment).
Cloud Foundry comes with support for a few “frameworks” (including Spring, Rails, Sinatra, Node.js, and Grails). Each framework is based on a “runtime” (including Java, Ruby 1.8, and Ruby 1.9). I found a brief description of how to add a new framework and a helpful write-up by someone who added Haskell & Happstack. Both of these seem to be focused on the old environment, and I will describe my experience in that environment before moving on to the “experimental” environment.
A Trivial Perl Application
While my eventual goal is to add Smalltalk, I wanted to start with a runtime based on executables that already exists in Cloud Foundry and selected Perl. (As will probably be evident, I’m not particularly strong in Perl and Ruby, so the following could probably be done better. You are welcome to add advice in the comments!) The first step was to build a Perl web application and I found one here. On my Mac (the “client” with respect to the cloud), I created a new directory (~/cloud/perl), and created three new files. The first, webserver.pl, is a copy of René Nyffenegger’s file with one change at line 77 to avoid an endless loop if there is nothing available on the port:
while (defined $request_line && $request_line ne "\r\n") {
The second, http_handler.pl, is modeled on René’s code (with help from Alvin Alexander), and follows:
# from http://www.adp-gmbh.ch/perl/webserver/index.html with modifications sub http_request_handler { my $fh = shift; my $req_ = shift; my %req = %$req_; my %header = %{$req{HEADER}}; print $fh "HTTP/1.0 200 OK\r\n"; print $fh "Server: adp perl webserver\r\n"; #print $fh "content-length: ... \r\n"; print $fh "\r\n"; print $fh "<html><h1>hello at "; print $fh scalar localtime(); print $fh "</h1></html>"; print $fh "Method: $req{METHOD}<br>"; print $fh "Object: $req{OBJECT}<br>"; foreach my $r (keys %header) { print $fh $r, " = ", $header{$r} , "<br>"; } # inspired by http://www.devdaily.com/perl/edu/articles/pl020001.shtml print $fh "<hr />"; foreach $key (sort keys(%ENV)) { print $fh "$key = $ENV{$key}<br>"; } } sub init_webserver_extension { $port_listen = $ENV{"VCAP_APP_PORT"} || 8888; } 1;
The third file, main.pl, is one line:
require "webserver.pl"
With these three files in a directory, we can run the application with the following shell command:
perl main.pl
Open a web browser and navigate to http://localhost:8888/ to see the application in operation, then in the client shell use <Ctrl>+<C> to stop the application. Our goal is to run this application on Cloud Foundry.
Changes to VMC on the Client
In order to push our Perl application we need to have VMC recognize it as a valid framework and this will require changes to the code in frameworks.rb. You can find the existing file with the following:
gem contents vmc | grep frameworks.rb
While we can modify the VMC gem directly, I believe that the proper way to do this is to rebuild the gem, starting with a checkout in an appropriate directory (e.g., ~/cloud/):
cd ~/cloud git clone https://github.com/cloudfoundry/vmc.git cd vmc git checkout -b addPerl bundle install bundle exec rake build
Now we edit lib/cli/frameworks.rb by inserting the following to the FRAMEWORKS at line 9:
'Perl' => ['perl', { :mem => '128M', :description => 'Perl Application'}],
Then we insert the following detection code staring at line 40 (after the Rails detection):
# Perl elsif File.exist?('main.pl') return Framework.lookup('Perl')
If you are modifying the installed gem directly, then you are done. Otherwise, you need to build and install the gem. To be extra proper, I modified lib/cli/version.rb to add ‘perl.1’ to the version number. Then, I entered the following shell commands:
gem build vmc.gemspec sudo gem install -f vmc-0.3.16.beta.2.perl.1.gem
This concludes the changes made on the client. As before, we need to log in to the server and in a server shell start VCAP (this is slightly different because we are using the traditional environment):
cd cloudfoundry/vcap bin/vcap start bin/vcap status
Then from the client we set up a tunnel to the cloud, set the target, create a user, and verify the info (described here in Targeting the Micro Cloud).
Changes to VCAP on the Server
There are three files on the server that need to be modified and two files that need to be created (one in a new directory). First, we modify the following:
vim ~/cloudfoundry/vcap/cloud_controller/app/models/app.rb
We want to modify lines 26-27 to add perl5 as a runtime and perl as a framework:
Runtimes = %w[perl5 ruby18 ruby19 java node php erlangR14B02 python26] Frameworks = %w[perl sinatra rails3 java_web spring grails node php otp_rebar lift wsgi django unknown]
Then we add three lines to normalize_legacy_staging_strings (starting at 541):
when "perl/1.0" self.framework = 'perl' self.runtime = 'perl5'
Then we modify the following:
vim ~/cloudfoundry/vcap/cloud_controller/config/cloud_controller.yml
We add two lines starting at 147:
perl5: version: 5.10
Then we modify the following:
vim ~/cloudfoundry/vcap/dea/config/dea.yml
We add the following six lines starting at line 44:
perl5: executable: /usr/bin/perl version: 5.10 version_flag: '-v' additional_checks: environment:
Next we create a new file:
vim ~/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/manifests/perl.yml
The contents of the file are modeled on the node.yml file:
--- name: "perl" runtimes: - perl5: version: '5.10' description: 'Perl 5' executable: perl default: true app_servers: detection: - "*.pl": '.' staged_services:
Then we need a new directory:
mkdir ~/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/perl/
Then we create a new file in that directory:
vim ~/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/perl/plugin.rb
The contents of that file are as follows:
class PerlPlugin < StagingPlugin
def framework 'perl' end
def stage_application Dir.chdir(destination_directory) do create_app_directories copy_source_files create_startup_script create_stop_script end end
def start_command cmds = [] cmds << "/usr/bin/perl main.pl" cmds.join("\n") end
private def startup_script vars = environment_hash generate_startup_script(vars) do "#no perl setup code needed" end end
def stop_script vars = environment_hash generate_stop_script(vars) end
end
With this file, we have our changes ready to be built and installed:
cd ~/cloudfoundry/vcap/staging rake build gem install vcap-staging gem contents vcap_staging | grep perl
Finally, we restart the cloud to pick up our changes:
cd ~/cloudfoundry/vcap/ bin/vcap restart
At this point we return to a client shell and see that Perl is a recognized framework:
vmc info vmc frameworks vmc runtimes
In the application directory on the client we can push the application to the server:
cd ~/cloud/perl vmc push
We name the app ‘perl-env’ and otherwise accept the defaults. In a web browser, navigate to http://perl-env.vcap.me/ and observe the application in operation. At this point you should be able to try the various commands listed at the end of this post.
Next we will investigate using an environment built using the new “experimental” script.
5 comments
Comments feed for this article
February 7, 2012 at 5:57 pm
Adding a Runtime and Framework to the New Cloud Foundry « Programming Gems (on GemStone)
[…] my previous post I described how to add a runtime and framework to a Cloud Foundry created with the traditional […]
February 14, 2012 at 9:26 pm
Preparing Smalltalk for Cloud Foundry « Programming Gems (on GemStone)
[…] cloud (coming in the next post), you should set up a client environment with VMC (as described here) with the following addition to lib/cli/frameworks.rb at line […]
March 13, 2012 at 6:23 pm
Adding Topaz as a Runtime in Cloud Foundry « Programming Gems (on GemStone)
[…] 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 […]
January 13, 2014 at 12:09 am
Vishal
Thanks for great post. While I understand the runtime addition from this post, I have some doubts on how to go about adding something like let’s say Oracle ESB or Tibco to CloudFoundry? Would you have any pointers towards that?
January 13, 2014 at 2:29 pm
James Foster
I’m not familiar enough with Oracle or Tibco to contribute much. Also, I’ll note that the newer Cloud Foundry does not support build-in services as the older Cloud Foundry did.