---
.../lib/deltacloud/drivers/gogrid/gogrid_driver.rb | 225 ++++++++++++++++++++
.../lib/deltacloud/drivers/gogrid/gogrid_test.rb | 73 +++++++
2 files changed, 298 insertions(+), 0 deletions(-)
create mode 100644 server/libexec/lib/deltacloud/drivers/gogrid/gogrid_driver.rb
create mode 100644 server/libexec/lib/deltacloud/drivers/gogrid/gogrid_test.rb
diff --git a/server/libexec/lib/deltacloud/drivers/gogrid/gogrid_driver.rb
b/server/libexec/lib/deltacloud/drivers/gogrid/gogrid_driver.rb
new file mode 100644
index 0000000..1593f79
--- /dev/null
+++ b/server/libexec/lib/deltacloud/drivers/gogrid/gogrid_driver.rb
@@ -0,0 +1,225 @@
+#
+# Copyright (C) 2009 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+require 'deltacloud/base_driver'
+require 'right_gogrid'
+
+module Deltacloud
+ module Drivers
+ module Gogrid
+
+class GogridDriver < Deltacloud::BaseDriver
+
+ # Storage capacity is same on all machines (10gb), it could be extended using
'Cloud Storage'
+ define_hardware_profile('server-with-512mb-ram') do
+ cpu 2
+ memory 0.5
+ storage 10
+ architecture 'i386'
+ end
+
+ define_hardware_profile('server-with-1gb-ram') do
+ cpu 2
+ memory 1
+ storage 10
+ architecture 'i386'
+ end
+
+ define_hardware_profile('server-with-2gb-ram') do
+ cpu 2
+ memory 2
+ storage 10
+ architecture 'i386'
+ end
+
+ define_hardware_profile('server-with-4gb-ram') do
+ cpu 2
+ memory 4
+ storage 10
+ architecture 'i386'
+ end
+
+ define_hardware_profile('server-with-8gb-ram') do
+ cpu 2
+ memory 8
+ storage 10
+ architecture 'i386'
+ end
+
+ # The only valid option for flavors is server RAM for now
+ def flavors(credentials, opts=nil)
+ results = []
+ safely do
+ gg=new_client(credentials)
+ results = gg.list_common_lookup('server.ram').collect do |sr|
+ Flavor.new(:id => sr['description'].downcase.tr(' ',
'-'), :memory => sr['name'], :architecture => 'i386')
+ end
+ end
+ return results if ( opts.nil? )
+ results = filter_on( results, :id, opts )
+ results = filter_on( results, :architecture, opts )
+ results
+ end
+
+ def images(credentials, opts=nil)
+ images = []
+ safely do
+ gg=new_client(credentials)
+ images = gg.list_images.collect { |image| convert_image(image, credentials[:name])
}
+ end
+ images = filter_on( images, :architecture, opts )
+ images.sort_by{|e| [e.owner_id,e.description]}
+ end
+
+ # gogrid doesn't supports realm yet (it's US/CA from whois)
+ def realms(credentials, opts=nil)
+ [Realm.new({
+ :id => "us",
+ :name => "United States",
+ :state => "AVAILABLE"
+ } )]
+ end
+
+ # Name consist from credentials name and timestamp
+ #
+ def create_instance(credentials, image_id, opts=nil)
+ flavor_id =(opts && opts[:flavor_id]) ? opts[:flavor_id] :
'server-with-512mb-ram'
+ # TODO: Fix naming here (IDEA: add 'name' to instance model)
+ name = 'Node '+Time.now.to_i.to_s
+ safely do
+ grid = new_client(credentials)
+ flavor = flavors(credentials).select { |f| f.id.eql?(flavor_id) }.first
+ image = images(credentials).select { |i| i.id.eql?(image_id) }.first
+ return convert_srv_to_instance(grid.add_server(name, image.name, flavor.memory,
get_free_ip(credentials), image.description), flavor_id)
+ end
+ end
+
+ def instances(credentials, opts=nil)
+ safely do
+ gg = new_client(credentials)
+ instances = gg.list_servers.collect { |server| convert_srv_to_instance(server,
convert_ram_to_flavor(server['ram']['name']))}
+ instances = filter_on( instances, :id, opts )
+ instances = filter_on( instances, :state, opts )
+ return instances
+ end
+ end
+
+ def reboot_instance(credentials, id)
+ safely do
+ gg = new_client(credentials)
+ return gg.gogrid_power_server(:power => 'restart', :name => id)
+ end
+ end
+
+ def stop_instance(credentials, id)
+ safely do
+ gg = new_client(credentials)
+ return gg.gogrid_power_server(:power => 'off', :name => id)
+ end
+ end
+
+ def destroy_instance(credentials, id)
+ safely do
+ gg = new_client(credentials)
+ gg.gogrid_delete_server(:name => id)
+ end
+ end
+
+
+ define_instance_states do
+ start.to( :on ) .on( :create )
+ pending.to( :on ) .automatically
+ running.to( :off ) .on( :reboot )
+ running.to( :off ) .on( :stop )
+ shutting_down.to( :off ) .automatically
+ stopped.to( :off ) .automatically
+ end
+
+ private
+
+ def convert_image(gg_image, owner_id=nil)
+ Image.new( {
+ :id=>gg_image['id'],
+ :name => gg_image['name'],
+ :description=>gg_image['friendlyName'],
+ :owner_id=>owner_id,
+ :architecture=>convert_arch(gg_image['description']),
+ } )
+ end
+
+ def new_client(credentials)
+ Rightscale::Gogrid.new(credentials.user, credentials.password)
+ end
+
+ # Determine architecture from description
+ def convert_arch(description)
+ return 'x86_64' if description.include?('64-bit')
+ return 'i386'
+ end
+
+ # NOTE: GoGrid doesn't use an ID for your instances. Instead they using a
'friendly name'
+ def convert_srv_to_instance(srv, flavor_id)
+ server = srv.kind_of?(Hash) ? srv : srv.first
+ Instance.new({
+ :id => server['name'],
+ :state => server['state']['name'],
+ :name => server['description'],
+ :image_id => server['image']['id'],
+ :owner_id => 'root',
+ :realm => 'us',
+ :public_addresses => server['ip']['ip'],
+ :private_addresses => nil,
+ :flavor_id => flavor_id,
+ :actions => instance_actions_for(server['state']['name'])
+ })
+ end
+
+ # We produce flavors from RAM
+ def convert_ram_to_flavor(ram)
+ 'server-with-'+ram.downcase+'-ram'
+ end
+
+ # You need a free IP from subnet you have assigned in case you want to start an
instance
+ def get_free_ip(credentials)
+ gg=new_client(credentials)
+ # TODO: I'm not sure about this, they changed API recently and right_gogrid
doesn't work well there
+ ip=gg.list_ips('Unassigned').select {|i| i['public'] }.last
+ return ip['ip'] if ip and ip['ip']
+ return nil
+ end
+
+ def safely(&block)
+ begin
+ block.call
+ rescue Rightscale::GogridError => e
+ if ( e.include?( /Forbidden/ ) )
+ raise Deltacloud::AuthException.new
+ else
+ e.errors.each do |error|
+ puts "ERROR #{error.inspect}"
+ end
+ end
+ end
+ end
+
+end
+
+ end
+ end
+end
+
+
diff --git a/server/libexec/lib/deltacloud/drivers/gogrid/gogrid_test.rb
b/server/libexec/lib/deltacloud/drivers/gogrid/gogrid_test.rb
new file mode 100644
index 0000000..ab2c5af
--- /dev/null
+++ b/server/libexec/lib/deltacloud/drivers/gogrid/gogrid_test.rb
@@ -0,0 +1,73 @@
+require 'lib/deltacloud/drivers/gogrid/gogrid_driver'
+require 'test/unit'
+
+CREDS = nil
+
+class GoGridTest < Test::Unit::TestCase
+
+ def test_valid_flavors
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ assert_kind_of Array, gd.flavors(CREDS)
+ assert_kind_of Flavor, gd.flavors(CREDS).first
+ end
+
+ def test_valid_images
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ assert_kind_of Array, gd.images(CREDS)
+ assert_kind_of Image, gd.images(CREDS).first
+ end
+
+ def test_create_instance
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ images = gd.images(CREDS)
+ assert_kind_of Array, images
+ instance = gd.create_instance(CREDS, images.first.id)
+ assert_kind_of Instance, instance
+ end
+
+ def test_list_instances
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ instances = gd.instances(CREDS)
+ assert_kind_of Array, instances
+ assert_kind_of Instance, instances.first
+ end
+
+ def test_get_instance
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ instances = gd.instances(CREDS)
+ if instances.kind_of?(Array)
+ assert_kind_of Instance, gd.instance(CREDS, { :id => instances.first.id })
+ end
+ end
+
+ def test_list_realms
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ assert_kind_of Array, gd.realms(CREDS)
+ assert_kind_of Realm, gd.realms(CREDS).first
+ end
+
+ # This tests fails anyway, because created instance isn't ready for it.
+ # If you want to really test, if these actions work properly, you could create an
instance
+ # first and change instances.last.id to ID of your instance. In this way tests will
work.
+
+ def test_reboot_instance
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ instances = gd.instances(CREDS)
+ assert_kind_of Hash, gd.reboot_instance(CREDS, instances.last.id)
+ end
+
+ def test_stop_instance
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ instances = gd.instances(CREDS)
+ assert_kind_of Hash, gd.stop_instance(CREDS, instances.last.id)
+ end
+
+ def test_destroy_instance
+ gd=Deltacloud::Drivers::Gogrid::GogridDriver.new
+ instances = gd.instances(CREDS)
+ assert_kind_of Hash, gd.destroy_instance(CREDS, instances.last.id)
+ end
+
+
+
+end
--
1.6.6.2