Return-Path: Delivered-To: apmail-incubator-deltacloud-dev-archive@minotaur.apache.org Received: (qmail 73976 invoked from network); 30 Nov 2010 22:12:44 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 30 Nov 2010 22:12:44 -0000 Received: (qmail 49501 invoked by uid 500); 30 Nov 2010 22:12:44 -0000 Delivered-To: apmail-incubator-deltacloud-dev-archive@incubator.apache.org Received: (qmail 49481 invoked by uid 500); 30 Nov 2010 22:12:44 -0000 Mailing-List: contact deltacloud-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: deltacloud-dev@incubator.apache.org Delivered-To: mailing list deltacloud-dev@incubator.apache.org Received: (qmail 49473 invoked by uid 99); 30 Nov 2010 22:12:44 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 30 Nov 2010 22:12:44 +0000 X-ASF-Spam-Status: No, hits=-5.0 required=10.0 tests=RCVD_IN_DNSWL_HI,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of tcrawley@redhat.com designates 209.132.183.28 as permitted sender) Received: from [209.132.183.28] (HELO mx1.redhat.com) (209.132.183.28) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 30 Nov 2010 22:12:35 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAUMCEhN027115 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 30 Nov 2010 17:12:14 -0500 Received: from katahdin.redhat.com (ovpn-113-116.phx2.redhat.com [10.3.113.116]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oAUMCCF5025671 for ; Tue, 30 Nov 2010 17:12:13 -0500 From: tcrawley@redhat.com To: deltacloud-dev@incubator.apache.org Subject: [PATCH] Allow for dynamic driver selection via header, storing it in Thread.current. Date: Tue, 30 Nov 2010 17:12:11 -0500 Message-Id: <1291155131-28542-2-git-send-email-tcrawley@redhat.com> In-Reply-To: <1291155131-28542-1-git-send-email-tcrawley@redhat.com> References: <1291155131-28542-1-git-send-email-tcrawley@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Virus-Checked: Checked by ClamAV on apache.org From: Tobias Crawley --- 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