incubator-deltacloud-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tcraw...@redhat.com
Subject [PATCH] Allow for dynamic driver selection via header, storing it in Thread.current.
Date Tue, 30 Nov 2010 22:12:11 GMT
From: Tobias Crawley <tcrawley@redhat.com>

---
 server/lib/drivers.rb                      |   97 +++++++++++++++-------------
 server/lib/sinatra/lazy_auth.rb            |    2 +-
 server/lib/sinatra/rabbit.rb               |    8 +-
 server/lib/sinatra/rack_driver_select.rb   |   22 ++++++
 server/server.rb                           |   41 ++++++++----
 server/views/api/drivers.xml.haml          |    6 ++
 server/views/api/show.html.haml            |    4 +-
 server/views/api/show.xml.haml             |    2 +-
 server/views/errors/backend_error.xml.haml |    2 +-
 server/views/layout.html.haml              |    2 +-
 10 files changed, 117 insertions(+), 69 deletions(-)
 create mode 100644 server/lib/sinatra/rack_driver_select.rb
 create mode 100644 server/views/api/drivers.xml.haml

diff --git a/server/lib/drivers.rb b/server/lib/drivers.rb
index 6e31bb7..43c5bea 100644
--- a/server/lib/drivers.rb
+++ b/server/lib/drivers.rb
@@ -1,51 +1,60 @@
-DRIVERS = {
-  :ec2 => { :name => "EC2" },
-  :rackspace => { :name => "Rackspace" },
-  :gogrid => { :name => "Gogrid" },
-  :rhevm => { :name => "RHEVM" },
-  :rimuhosting => { :name => "RimuHosting"},
-  :opennebula => { :name => "Opennebula", :class => "OpennebulaDriver" },
-  :terremark => { :name => "Terremark"},
-  :azure => { :name => "Azure" },
-  :mock => { :name => "Mock" }
-}
-
-DEFAULT_COLLECTIONS = [
-  :hardware_profiles,
-  :images,
-  :instances,
-  :instance_states,
-  :realms,
-  :storage_volumes,
-  :storage_snapshots
-]
-
-DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
-
-def driver_name
-  DRIVERS[DRIVER][:name]
-end
-
-def driver_class_name
-  basename = DRIVERS[DRIVER][:class] || "#{driver_name}Driver"
-  "Deltacloud::Drivers::#{driver_name}::#{basename}"
-end
+module Deltacloud
+  DRIVERS = {
+    :ec2 => { :name => "EC2" },
+    :rackspace => { :name => "Rackspace" },
+    :gogrid => { :name => "Gogrid" },
+    :rhevm => { :name => "RHEVM" },
+    :rimuhosting => { :name => "RimuHosting"},
+    :opennebula => { :name => "Opennebula", :class => "OpennebulaDriver" },
+    :terremark => { :name => "Terremark"},
+    :azure => { :name => "Azure" },
+    :mock => { :name => "Mock" }
+  }
+
+  DEFAULT_COLLECTIONS = [
+    :hardware_profiles,
+    :images,
+    :instances,
+    :instance_states,
+    :realms,
+    :storage_volumes,
+    :storage_snapshots
+  ]
+
+  DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
+
+  def driver_symbol
+    (Thread.current[:driver] || DRIVER).to_sym
+  end
 
-def driver_source_name
-  File.join("deltacloud", "drivers", "#{DRIVER}", "#{DRIVER}_driver.rb")
-end
+  def driver_name
+    DRIVERS[:"#{driver_symbol}"][:name]
+  end
 
-def driver_mock_source_name
-  return File.join('deltacloud', 'drivers', DRIVER.to_s, "#{DRIVER}_driver.rb") if driver_name.eql?
'Mock'
-end
+  def driver_class_name
+    basename = DRIVERS[:"#{driver_symbol}"][:class] || "#{driver_name}Driver"
+    "Deltacloud::Drivers::#{driver_name}::#{basename}"
+  end
 
-def driver
-  require driver_source_name
-  #require 'deltacloud/base_driver/mock_driver.rb'
+  def driver_source_name
+    File.join("deltacloud", "drivers", "#{driver_symbol}", "#{driver_symbol}_driver.rb")
+  end
 
-  if Sinatra::Application.environment.eql? :test
-    require driver_mock_source_name if driver_mock_source_name
+  def driver_mock_source_name
+    return File.join('deltacloud', 'drivers', "#{driver_symbol}", 
+                     "#{driver_symbol}_driver.rb") if driver_name.eql? 'Mock'
   end
 
-  @driver ||= eval( driver_class_name ).new
+  def driver
+    require driver_source_name
+    #require 'deltacloud/base_driver/mock_driver.rb'
+
+    if Sinatra::Application.environment.eql? :test
+      require driver_mock_source_name if driver_mock_source_name
+    end
+
+    @driver ||= eval( driver_class_name ).new
+  end
 end
+
+include Deltacloud
diff --git a/server/lib/sinatra/lazy_auth.rb b/server/lib/sinatra/lazy_auth.rb
index 2a26fdf..99c416a 100644
--- a/server/lib/sinatra/lazy_auth.rb
+++ b/server/lib/sinatra/lazy_auth.rb
@@ -40,7 +40,7 @@ module Sinatra
     end
 
     def authorize!
-      r = "#{DRIVER}-deltacloud@#{HOSTNAME}"
+      r = "#{driver_symbol}-deltacloud@#{HOSTNAME}"
       response['WWW-Authenticate'] = %(Basic realm="#{r}")
       throw(:halt, [401, "Not authorized\n"])
     end
diff --git a/server/lib/sinatra/rabbit.rb b/server/lib/sinatra/rabbit.rb
index 94c74e3..05bd6c5 100644
--- a/server/lib/sinatra/rabbit.rb
+++ b/server/lib/sinatra/rabbit.rb
@@ -60,7 +60,7 @@ module Sinatra
       def control(&block)
         op = self
         @control = Proc.new do
-          op.check_capability(driver)
+          op.check_capability(Deltacloud::driver)
           op.validate(params)
           instance_eval(&block)
         end
@@ -133,7 +133,7 @@ module Sinatra
       end
 
       def generate_documentation
-        coll, oper, features = self, @operations, driver.features(name)
+        coll, oper, features = self, @operations, Deltacloud::driver.features(name)
         ::Sinatra::Application.get("/api/docs/#{@name}") do
           @collection, @operations, @features = coll, oper, features
           respond_to do |format|
@@ -206,9 +206,9 @@ module Sinatra
     # operation on this collection.
     def collection(name, &block)
       raise DuplicateCollectionException if collections[name]
-      return unless driver.has_collection?(name.to_sym)
+      return unless Deltacloud::driver.has_collection?(name.to_sym)
       collections[name] = Collection.new(name, &block)
-      collections[name].add_feature_params(driver.features(name))
+      collections[name].add_feature_params(Deltacloud::driver.features(name))
       collections[name].generate
     end
 
diff --git a/server/lib/sinatra/rack_driver_select.rb b/server/lib/sinatra/rack_driver_select.rb
new file mode 100644
index 0000000..24c36de
--- /dev/null
+++ b/server/lib/sinatra/rack_driver_select.rb
@@ -0,0 +1,22 @@
+class RackDriverSelect
+
+  def initialize(app, opts={})
+    @app = app
+    @opts = opts
+  end
+
+  def call(env)
+    original_driver = Thread.current[:driver]
+    new_driver = extract_driver(env)
+    Thread.current[:driver] = new_driver if new_driver
+    @app.call(env)
+  ensure
+    Thread.current[:driver] = original_driver
+  end
+
+  def extract_driver(env)
+    driver_name = env['HTTP_HEADERS'].match(/X\-Deltacloud\-Driver:(\w+)/i).to_a
+    return driver_name[1] if driver_name[1]
+  end
+
+end
diff --git a/server/server.rb b/server/server.rb
index d3f7d8a..076859d 100644
--- a/server/server.rb
+++ b/server/server.rb
@@ -10,6 +10,12 @@ require 'erb'
 require 'haml'
 require 'open3'
 require 'lib/deltacloud/helpers/blob_stream'
+require 'sinatra/rack_driver_select'
+
+set :version, '0.1.0'
+
+
+use RackDriverSelect
 
 configure do
   set :raise_errors => false
@@ -48,23 +54,28 @@ Sinatra::Application.register Sinatra::RespondTo
 # Redirect to /api
 get '/' do redirect url_for('/api'); end
 
+get '/api/drivers\/?' do
+  respond_to do |format|
+    format.xml { haml :"api/drivers" }
+  end
+end
+
 get '/api\/?' do
-    @version = 0.1
-    if params[:force_auth]
-      return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
-    end
-    respond_to do |format|
-        format.xml { haml :"api/show" }
-        format.json do
-          { :api => {
-            :version => @version,
-            :driver => DRIVER,
-            :links => entry_points.collect { |l| { :rel => l[0], :href => l[1]}
}
-            }
-          }.to_json
-        end
-        format.html { haml :"api/show" }
+  if params[:force_auth]
+    return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
+  end
+  respond_to do |format|
+    format.xml { haml :"api/show" }
+    format.json do
+      { :api => {
+          :version => settings.version,
+          :driver => driver_symbol,
+          :links => entry_points.collect { |l| { :rel => l[0], :href => l[1]} }
+        }
+      }.to_json
     end
+    format.html { haml :"api/show" }
+  end
 end
 
 # Rabbit DSL
diff --git a/server/views/api/drivers.xml.haml b/server/views/api/drivers.xml.haml
new file mode 100644
index 0000000..7beb9c8
--- /dev/null
+++ b/server/views/api/drivers.xml.haml
@@ -0,0 +1,6 @@
+%api{ :version => settings.version }
+  %drivers
+    - DRIVERS.each do |id, details|
+      %driver{ :id => id }
+        %name<
+          =details[:name]
diff --git a/server/views/api/show.html.haml b/server/views/api/show.html.haml
index 0077972..74ec175 100644
--- a/server/views/api/show.html.haml
+++ b/server/views/api/show.html.haml
@@ -1,5 +1,5 @@
 %h1
-  API v#{@version}
+  API v#{settings.version}
 
 %ul
   - collections.keys.sort_by { |k| k.to_s }.each do |key|
@@ -12,4 +12,4 @@
             = op
   %li
     %strong
-      %a{:href => url_for("/api/docs")} Documentation (v#{@version})
+      %a{:href => url_for("/api/docs")} Documentation (#{settings.version})
diff --git a/server/views/api/show.xml.haml b/server/views/api/show.xml.haml
index 70c26c9..f68fd79 100644
--- a/server/views/api/show.xml.haml
+++ b/server/views/api/show.xml.haml
@@ -1,4 +1,4 @@
-%api{ :version=>@version, :driver=>DRIVER }
+%api{ :version => settings.version, :driver => driver_symbol }
   - for entry_point in entry_points
     %link{ :rel=>entry_point[0], :href=>entry_point[1] }
       - for feature in driver.features(entry_point[0])
diff --git a/server/views/errors/backend_error.xml.haml b/server/views/errors/backend_error.xml.haml
index 75866eb..4aba8c0 100644
--- a/server/views/errors/backend_error.xml.haml
+++ b/server/views/errors/backend_error.xml.haml
@@ -1,6 +1,6 @@
 %error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
   %kind backend_error
-  %backend{ :driver => DRIVER }
+  %backend{ :driver => driver_symbol }
     %code= @error.code
     %cause= @error.cause
     - if @error.details
diff --git a/server/views/layout.html.haml b/server/views/layout.html.haml
index c46b15b..1556272 100644
--- a/server/views/layout.html.haml
+++ b/server/views/layout.html.haml
@@ -19,7 +19,7 @@
         = yield
       #footer
         #driver_info
-          Driver: #{DRIVER}
+          Driver: #{driver_symbol} | API version: #{settings.version}
         #copyright
           Copyright 2009, 2010
           %a{:href => 'http://redhat.com'} Red Hat
-- 
1.7.3.2


Mime
View raw message