You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltacloud.apache.org by lu...@apache.org on 2010/07/09 01:45:52 UTC

svn commit: r962317 - in /incubator/deltacloud/trunk/server/lib: deltacloud/drivers/terremark/ deltacloud/drivers/terremark/terremark_driver.rb drivers.rb

Author: lutter
Date: Thu Jul  8 23:45:51 2010
New Revision: 962317

URL: http://svn.apache.org/viewvc?rev=962317&view=rev
Log:
Terremark vcloud express driver	v0.2 [NEEDS FOG >= 0.0.93]

Added:
    incubator/deltacloud/trunk/server/lib/deltacloud/drivers/terremark/
    incubator/deltacloud/trunk/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
Modified:
    incubator/deltacloud/trunk/server/lib/drivers.rb

Added: incubator/deltacloud/trunk/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/server/lib/deltacloud/drivers/terremark/terremark_driver.rb?rev=962317&view=auto
==============================================================================
--- incubator/deltacloud/trunk/server/lib/deltacloud/drivers/terremark/terremark_driver.rb (added)
+++ incubator/deltacloud/trunk/server/lib/deltacloud/drivers/terremark/terremark_driver.rb Thu Jul  8 23:45:51 2010
@@ -0,0 +1,261 @@
+# Copyright (C) 2010  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
+#
+# This driver uses the fog library (Geemus - Wesley Beary) to talk to terremark... see
+#                                   http://github.com/geemus/fog
+# see terremark vcloud express api at:
+# https://community.vcloudexpress.terremark.com/en-us/product_docs/w/wiki/d-complete-vcloud-express-api-document.aspx
+#
+# 02 May 2010
+#
+require 'deltacloud/base_driver'
+require 'fog'
+require 'excon'
+require 'nokogiri'
+
+module Deltacloud
+  module Drivers
+    module Terremark
+
+class TerremarkDriver < Deltacloud::BaseDriver
+
+  feature :instances, :user_name
+
+#--
+# Vapp State Map... for use with convert_instance (get an integer back from terremark)
+#--
+VAPP_STATE_MAP = { "0" =>  "PENDING", "1" =>  "PENDING", "2" =>  "STOPPED", "4" =>  "RUNNING" }
+
+#--
+# HARDWARE PROFILES
+#--
+  define_hardware_profile 'default' do
+    cpu   [1,2,4,8]
+    memory  [512, 1024, 2048, 4096, 8192]
+    storage (1..500).to_a
+  end
+  #storage_disks [1..15]
+
+#--
+# IMAGES
+#--
+#aka "vapp_templates"
+  def images(credentials, opts=nil)
+      image_list = []
+      terremark_client = new_client(credentials)
+      vdc_id = terremark_client.default_vdc_id
+      catalogItems = terremark_client.get_catalog(vdc_id).body['CatalogItems']
+      catalogItems.each{ |catalog_item|
+        current_item_id = catalog_item['href'].split('/').last
+        current_item = terremark_client.get_catalog_item(current_item_id).body['Entity']
+          if(current_item['type'] == 'application/vnd.vmware.vcloud.vAppTemplate+xml')
+            image_list << convert_image(current_item, credentials.user)
+          end
+      } #end of catalogItems.each
+      image_list = filter_on( image_list, :id, opts )
+      image_list = filter_on( image_list, :architecture, opts )
+      image_list = filter_on( image_list, :owner_id, opts )
+      image_list
+  end
+
+#--
+# REALMS
+#--
+#only one realm... everything in US?
+  def realms(credentials, opts=nil)
+     [Realm.new( {
+      :id=>"US-Miami",
+      :name=>"United States - Miami",
+      :state=> "AVAILABLE"
+    } )]
+  end
+
+#--
+# INSTANCES
+#--
+#aka vApps
+  def instances(credentials, opts=nil)
+      instances = []
+      terremark_client = new_client(credentials)
+      vdc_items = terremark_client.get_vdc(terremark_client.default_vdc_id()).body['ResourceEntities']
+      vdc_items.each{|current_item|
+        if(current_item['type'] == 'application/vnd.vmware.vcloud.vApp+xml')
+           vapp_id =  current_item['href'].split('/').last
+           vapp = terremark_client.get_vapp(vapp_id)
+           instances  << convert_instance(vapp, terremark_client, credentials.user)
+        end
+      }#end vdc_items.each
+      instances = filter_on( instances, :id, opts )
+      instances
+  end
+
+#--
+# FINITE STATE MACHINE
+#--
+#by default new instance --> powered_off
+  define_instance_states do
+    start.to(:pending)            .on( :create )
+    pending.to(:stopped)          .automatically
+    stopped.to(:running)          .on( :start )
+    running.to(:running)          .on( :reboot )
+    running.to(:shutting_down)    .on( :stop )
+    shutting_down.to(:stopped)    .automatically
+    stopped.to(:end)              .on( :destroy )
+   end
+
+
+#--
+# CREATE INSTANCE
+#--
+#launch a vapp template. Needs a name, ram, no. cpus, id of vapp_template
+  def create_instance(credentials, image_id, opts)
+    new_vapp = nil
+    vapp_opts = {} #assemble options to pass to Fog::Terremark::Real.instantiate_vapp_template
+    terremark_hwp = hardware_profiles(credentials, {:name => 'default'}).first #sanity check values against default
+    name = opts['name'] #name could be nil or length 0 or too long
+    name = "inst#{Time.now.to_i}" if (name.nil? || (name.length == 0))
+    name = name.slice(0..13) #name < 15 chars (says terremark)
+    unless ( (terremark_hwp.include?(:cpu, opts[:hwp_cpu].to_i)) &&
+              (terremark_hwp.include?(:memory, opts[:hwp_memory].to_i)) ) then
+       raise Deltacloud::Validation::Failure.new(Deltacloud::Validation::Param.new(["cpu"]), "Error with cpu and/or memory values. you said cpu->#{opts[:hwp_cpu]} and mem->#{opts[:hwp_memory]}")
+    end
+    vapp_opts['cpus'] = opts[:hwp_cpu]
+    vapp_opts['memory'] =  opts[:hwp_memory]
+    terremark_client = new_client(credentials)
+#######
+#FIXME#  what happens if there is an issue getting the new vapp id? (eg even though created succesfully)
+#######
+    vapp_id = terremark_client.instantiate_vapp_template(name, image_id, vapp_opts).body['href'].split('/').last
+    new_vapp = terremark_client.get_vapp(vapp_id)
+    return convert_instance(new_vapp, terremark_client, credentials.user) #return an Instance object
+  end
+
+#--
+# REBOOT INSTANCE
+#--
+  def reboot_instance(credentials, id)
+    terremark_client =  new_client(credentials)
+    terremark_client.power_reset(id)
+  end
+
+#--
+# START INSTANCE
+#--
+def start_instance(credentials, id)
+    terremark_client =  new_client(credentials)
+    terremark_client.power_on(id)
+end
+
+#--
+# STOP INSTANCE
+#--
+def stop_instance(credentials, id)
+    terremark_client = new_client(credentials)
+    terremark_client.power_shutdown(id)
+end
+
+#--
+# DESTROY INSTANCE
+#--
+#shuts down... in terremark need to do a futher delete to get rid of a vapp entirely
+def destroy_instance(credentials, id)
+    terremark_client = new_client(credentials)
+    terremark_client.delete_vapp(id)
+end
+
+#--
+# PRIVATE METHODS:
+#--
+
+ private
+
+#--
+# CONVERT IMAGE
+#--
+#gets a vapp_template from a catalog and makes it a Image
+  def convert_image(catalog_vapp_template, account_name)
+    name = catalog_vapp_template['name']
+    #much fudging ensues
+    #arch = name.scan(/(36|24).bit/).first
+    #k enuf o'that now!
+    arch = "n/a" #Leaving out entirely as we don't get one from terremark (could parse but its a fudge)
+    Image.new( {
+                  :id => catalog_vapp_template['href'].split('/').last,
+                  :name => catalog_vapp_template['name'],
+                  :architecture => arch,
+                  :owner_id => account_name,
+                  :description => catalog_vapp_template['name']
+               })
+  end
+
+#--
+# CONVERT INSTANCE
+#--
+  def convert_instance(vapp, terremark_client, account_name)
+      vapp_private_ip = vapp.body['IpAddress']
+      vapp_public_ip = terremark_client.get_public_ips(terremark_client.default_vdc_id).body['PublicIpAddresses'].first['name']#get_public_address(terremark_client, vapp_private_ip)
+      vapp_status = vapp.body['status']
+      current_state = VAPP_STATE_MAP[vapp_status] #status == 0->BEING_CREATED 2->OFF 4->ON
+      profile = InstanceProfile.new("default")
+      name = vapp.body['name']
+      if current_state != "PENDING" #can only grab this stuff after instance is created
+        profile.cpu = vapp.body['VirtualHardware']['cpu']
+        profile.memory = vapp.body['VirtualHardware']['ram']
+#######
+#FIXME# could be more that one disk... but for now capture only first
+#######
+        disk = ((vapp.body['VirtualHardware']['disks'].first.to_i) / 1024 / 1024).to_s
+        profile.storage = disk
+#######
+#FIXME# this is a hack, shouldn't place this info next to name as some clients may rely on name field... probably will introduce
+####### a new field in the API for this (e.g. description/text field... human readable)
+      #name = "#{name} - [ #{vapp.body['OperatingSystem']['Description']} ]"
+      end
+      Instance.new( {
+                    :id => vapp.body['href'].split('/').last,
+                    :owner_id => "#{account_name}",
+                    #:image_id => "n/a", #cant get this... see https://community.vcloudexpress.terremark.com/en-us/discussion_forums/f/60/t/376.aspx
+                    :name => name,
+                    :realm_id => "US-Miami",
+                    :state => current_state,
+                    :actions => instance_actions_for(current_state),
+                    :public_addresses => vapp_public_ip,
+                    :private_addresses => vapp_private_ip,
+                    :instance_profile => profile
+                    } )
+  end
+
+#--
+# NEW CLIENT
+#--
+#use supplied credentials to make a new client for talking to terremark
+  def new_client(credentials)
+    #Fog constructor expecting  credentials[:terremark_password] and credentials[:terremark_username]
+    terremark_credentials = {:terremark_vcloud_username => "#{credentials.user}", :terremark_vcloud_password => "#{credentials.password}" }
+    terremark_client = Fog::Terremark::Vcloud.new(terremark_credentials)
+    vdc_id = terremark_client.default_vdc_id
+    if (vdc_id.nil?)
+       raise DeltaCloud::AuthException.new
+    end
+    terremark_client
+  end
+
+
+end
+
+    end
+  end
+end

Modified: incubator/deltacloud/trunk/server/lib/drivers.rb
URL: http://svn.apache.org/viewvc/incubator/deltacloud/trunk/server/lib/drivers.rb?rev=962317&r1=962316&r2=962317&view=diff
==============================================================================
--- incubator/deltacloud/trunk/server/lib/drivers.rb (original)
+++ incubator/deltacloud/trunk/server/lib/drivers.rb Thu Jul  8 23:45:51 2010
@@ -5,6 +5,7 @@ DRIVERS = {
   :rhevm => { :name => "RHEVM" },
   :rimu => { :name => "Rimu", :class => "RimuHostingDriver"},
   :opennebula => { :name => "Opennebula", :class => "OpennebulaDriver" },
+  :terremark => { :name => "Terremark"},
   :mock => { :name => "Mock" }
 }
 
@@ -27,15 +28,7 @@ def driver_mock_source_name
 end
 
 def driver
-
-  begin
-    require driver_source_name
-  rescue LoadError => e
-    gem_name = e.message.match(/ -- (.+)$/).to_a.last
-    gem_name = "amazon-ec2" if gem_name.eql?('AWS')
-    $stderr.puts "ERROR: Please install required gem first. (gem install #{gem_name})"
-    exit 1
-  end
+  require driver_source_name
 
   if Sinatra::Application.environment.eql? :test
     require driver_mock_source_name