You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by lu...@redhat.com on 2011/03/29 01:41:19 UTC
Make drivers a toplevel collection
We've had an XML representation of drivers supported by the server as a
one-off page for a while now. In keeping with HATEAOS, the list of drivers
should be reachable through the main API entry point.
To make that possible, I turned drivers into their own toplevel
collection. I also changed the XML format for a driver to emphasize the
list of possible provider values more. For the EC2 driver the XML now is:
<driver href="http://localhost:3001/api/drivers/ec2" id="ec2">
<name>EC2</name>
<provider id="us-west-1">
<entrypoint kind="s3">s3-us-west-1.amazonaws.com</entrypoint>
<entrypoint kind="elb">elasticloadbalancing.us-west-1.amazonaws.com</entrypoint>
<entrypoint kind="ec2">ec2.us-west-1.amazonaws.com</entrypoint>
</provider>
.. similar provider tags for the other regions ..
</driver>
David
[PATCH 2/3] drivers: new collection
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
---
.../lib/deltacloud/helpers/application_helper.rb | 14 ++++++
server/server.rb | 43 ++++++++++++++++---
server/views/api/drivers.html.haml | 14 ------
server/views/api/drivers.xml.haml | 11 -----
server/views/api/show.html.haml | 2 +-
server/views/drivers/index.html.haml | 15 +++++++
server/views/drivers/index.xml.haml | 7 +++
7 files changed, 73 insertions(+), 33 deletions(-)
delete mode 100644 server/views/api/drivers.html.haml
delete mode 100644 server/views/api/drivers.xml.haml
create mode 100644 server/views/drivers/index.html.haml
create mode 100644 server/views/drivers/index.xml.haml
diff --git a/server/lib/deltacloud/helpers/application_helper.rb b/server/lib/deltacloud/helpers/application_helper.rb
index 4ee0480..345aaff 100644
--- a/server/lib/deltacloud/helpers/application_helper.rb
+++ b/server/lib/deltacloud/helpers/application_helper.rb
@@ -204,4 +204,18 @@ module ApplicationHelper
"#{text[0..(length/2)]}#{end_string}"
end
+ # Reverse the entrypoints hash for a driver from drivers.yaml; note that
+ # +d+ is a hash, not an actual driver object
+ def driver_provider(d)
+ result = {}
+ if d[:entrypoints]
+ d[:entrypoints].each do |kind, details|
+ details.each do |prov, url|
+ result[prov] ||= {}
+ result[prov][kind] = url
+ end
+ end
+ end
+ result
+ end
end
diff --git a/server/server.rb b/server/server.rb
index 3c4273c..d287031 100644
--- a/server/server.rb
+++ b/server/server.rb
@@ -83,17 +83,11 @@ Sinatra::Application.register Sinatra::RespondTo
# Redirect to /api
get '/' do redirect url_for('/api'), 301; end
-get '/api/drivers\/?' do
- respond_to do |format|
- format.xml { haml :"api/drivers" }
- format.html { haml :"api/drivers" }
- end
-end
-
get '/api\/?' do
if params[:force_auth]
return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
end
+ @collections = [:drivers] + driver.supported_collections
respond_to do |format|
format.xml { haml :"api/show" }
format.json do
@@ -110,6 +104,41 @@ end
# Rabbit DSL
+collection :drivers do
+ global!
+
+ description <<EOS
+List all the drivers supported by this server.
+EOS
+
+ operation :index do
+ description "List all drivers"
+ control do
+ @drivers = settings.drivers
+ respond_to do |format|
+ format.xml { haml :"drivers/index" }
+ format.json { @drivers.to_json }
+ format.html { haml :"drivers/index" }
+ end
+ end
+ end
+
+ operation :show do
+ description "Show details for a driver"
+ param :id, :string
+ control do
+ @name = params[:id].to_sym
+ @driver = settings.drivers[@name]
+ return [404, "Driver #{@name} not found"] unless @driver
+ respond_to do |format|
+ format.xml { haml :"drivers/show" }
+ format.json { @driver.to_json }
+ format.html { haml :"drivers/show" }
+ end
+ end
+ end
+end
+
collection :realms do
description <<END
Within a cloud provider a realm represents a boundary containing resources.
diff --git a/server/views/api/drivers.html.haml b/server/views/api/drivers.html.haml
deleted file mode 100644
index 9eef8cf..0000000
--- a/server/views/api/drivers.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-%h1
- Available Drivers
-
-%table.display
- %thead
- %tr
- %th ID
- %th Name
- %tbody
- - settings.drivers.each do |id, details|
- %tr
- %td{ :width => '20%' }
- %tt= id
- %td= details[:name]
diff --git a/server/views/api/drivers.xml.haml b/server/views/api/drivers.xml.haml
deleted file mode 100644
index 93975f0..0000000
--- a/server/views/api/drivers.xml.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-%api{ :version => settings.version }
- %drivers
- - settings.drivers.each do |id, details|
- %driver{ :id => id }
- %name<
- =details[:name]
- - if details[:entrypoints]
- - details[:entrypoints].each do |list_id, entrypoints|
- %entrypoints{:id => list_id}
- - entrypoints.each do |entrypoint, url|
- %entrypoint{ :id => entrypoint }<=cdata(url)
diff --git a/server/views/api/show.html.haml b/server/views/api/show.html.haml
index 199c9fd..287b989 100644
--- a/server/views/api/show.html.haml
+++ b/server/views/api/show.html.haml
@@ -2,7 +2,7 @@
Deltacloud API #{settings.version}
%ul
- - driver.supported_collections.sort_by { |k| k.to_s }.each do |key|
+ - @collections.sort_by { |k| k.to_s }.each do |key|
%li
= link_to key.to_s.gsub('_', ' ').titlecase, url_for("/api/#{key}")
%dl
diff --git a/server/views/drivers/index.html.haml b/server/views/drivers/index.html.haml
new file mode 100644
index 0000000..fc35115
--- /dev/null
+++ b/server/views/drivers/index.html.haml
@@ -0,0 +1,15 @@
+%h1
+ Available Drivers
+
+%table.display
+ %thead
+ %tr
+ %th ID
+ %th Name
+ %tbody
+ - @drivers.each do |id, details|
+ %tr
+ %td{ :width => '20%' }
+ %tt
+ %a{ :href => driver_url(id) }= id
+ %td= details[:name]
diff --git a/server/views/drivers/index.xml.haml b/server/views/drivers/index.xml.haml
new file mode 100644
index 0000000..63e809f
--- /dev/null
+++ b/server/views/drivers/index.xml.haml
@@ -0,0 +1,7 @@
+%drivers
+ - @drivers.each do |id, details|
+ %driver{ :href => driver_url(id), :id => id }
+ %name<
+ =details[:name]
+ - driver_provider(details).keys.each do |prov|
+ %provider{ :id => prov }
--
1.7.4
[PATCH 3/3] Driver docs: explain how to switch drivers dynamically
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
---
site/content/_drivers.mdown | 30 +++++++++++++-
site/output/drivers.html | 95 +++++++++++++++++++++++++++++-------------
2 files changed, 93 insertions(+), 32 deletions(-)
diff --git a/site/content/_drivers.mdown b/site/content/_drivers.mdown
index f952875..ed87d23 100644
--- a/site/content/_drivers.mdown
+++ b/site/content/_drivers.mdown
@@ -5,8 +5,6 @@ can handle a set of standard operations, some of them also support a number of
optional operations to expose the features of specific clouds more closely. The
drivers and their capabilities are:
-<table providers></table>
-
## Setting up the code
To set up a Deltacloud core and the drivers, install the
@@ -29,6 +27,34 @@ This will start a webserver running the mock driver on
`http://localhost:3001/api`; you can simply browse to that URL to get a
pretty view of the objects the driver deals with.
+## Dynamic driver switching
+
+The driver specified with the `-i` switch when `deltacloudd` is launched is
+the default driver. Clients can switch drivers for any request. The list of
+drivers supported by the server can be obtained from the `drivers`
+collection.
+
+Some drivers also support the notion of a *provider*. Changing the provider
+makes it possible to use the same driver against different instances of a
+cloud, for example different regions in EC2 or different installations of
+RHEV-M. The possible range of values for the provider is driver-specific.
+
+The driver and provider can be selected in one of two ways:
+
+1. Through the request headers `X-Deltacloud-Driver` and
+ `X-Deltacloud-Provider`. For example, including the headers
+ `X-Deltacloud-Driver: ec2` and `X-Deltacloud-Provider: eu-west-1`
+ ensures that a request will be serviced by the EC2 driver, and that the
+ driver will use the eu-west-1 region in EC2.
+2. Through the matrix request parameters `driver` and `provider` in the
+ `api` component of the server's URL. For example, requesting
+ `http://localhost:3001/api;driver=ec2;provider=eu-west-1` has the same
+ effect as using the two request headers mentioned above.
+
+## Notes on specific drivers
+
+<table providers></table>
+
### EC2 Driver
For the Amazon EC2 you need to install the `amazon-ec2` Ruby gem:
diff --git a/site/output/drivers.html b/site/output/drivers.html
index 3494813..5dcc2cc 100644
--- a/site/output/drivers.html
+++ b/site/output/drivers.html
@@ -82,21 +82,27 @@
</li>
<li>
<a href="#h2">Launch the server</a>
+ </li>
+ <li>
+ <a href="#h3">Dynamic driver switching</a>
+ </li>
+ <li>
+ <a href="#h4">Notes on specific drivers</a>
<ul>
<li>
- <a href="#h2_1">EC2 Driver</a>
+ <a href="#h4_1">EC2 Driver</a>
</li>
<li>
- <a href="#h2_2">RHEV-M Driver</a>
+ <a href="#h4_2">RHEV-M Driver</a>
</li>
<li>
- <a href="#h2_3">Rackspace Driver</a>
+ <a href="#h4_3">Rackspace Driver</a>
</li>
<li>
- <a href="#h2_4">RimuHosting</a>
+ <a href="#h4_4">RimuHosting</a>
</li>
<li>
- <a href="#h2_5">OpenNebula</a>
+ <a href="#h4_5">OpenNebula</a>
</li>
</ul></li></ul>
<!-- = rest -->
@@ -106,6 +112,55 @@
can handle a set of standard operations, some of them also support a number of
optional operations to expose the features of specific clouds more closely. The
drivers and their capabilities are:</p>
+
+ <h2 id="h1">Setting up the code</h2>
+
+ <p>To set up a Deltacloud core and the drivers, install the
+ <a href="http://rubygems.org/gems/deltacloud-core">deltacloud-core</a> Ruby gem:</p>
+
+ <pre><code># gem install deltacloud-core
</code></pre>
+
+ <p>RPM package will be available soon.</p>
+
+ <h2 id="h2">Launch the server</h2>
+
+ <p>The server is launched with the <code>deltacloudd</code> command and pass it the name
+ of the driver you want to use:</p>
+
+ <pre><code>$ deltacloudd -i mock
</code></pre>
+
+ <p>This will start a webserver running the mock driver on
+ <code>http://localhost:3001/api</code>; you can simply browse to that URL to get a
+ pretty view of the objects the driver deals with.</p>
+
+ <h2 id="h3">Dynamic driver switching</h2>
+
+ <p>The driver specified with the <code>-i</code> switch when <code>deltacloudd</code> is launched is
+ the default driver. Clients can switch drivers for any request. The list of
+ drivers supported by the server can be obtained from the <code>drivers</code>
+ collection.</p>
+
+ <p>Some drivers also support the notion of a <em>provider</em>. Changing the provider
+ makes it possible to use the same driver against different instances of a
+ cloud, for example different regions in EC2 or different installations of
+ RHEV-M. The possible range of values for the provider is driver-specific.</p>
+
+ <p>The driver and provider can be selected in one of two ways:</p>
+
+ <ol>
+ <li>Through the request headers <code>X-Deltacloud-Driver</code> and
+ <code>X-Deltacloud-Provider</code>. For example, including the headers
+ <code>X-Deltacloud-Driver: ec2</code> and <code>X-Deltacloud-Provider: eu-west-1</code>
+ ensures that a request will be serviced by the EC2 driver, and that the
+ driver will use the eu-west-1 region in EC2.</li>
+ <li>Through the matrix request parameters <code>driver</code> and <code>provider</code> in the
+ <code>api</code> component of the server's URL. For example, requesting
+ <code>http://localhost:3001/api;driver=ec2;provider=eu-west-1</code> has the same
+ effect as using the two request headers mentioned above.</li>
+ </ol>
+
+
+ <h2 id="h4">Notes on specific drivers</h2>
<h3>Compute Drivers</h3>
<table id='providers'>
<tr>
@@ -340,27 +395,7 @@
- <h2 id="h1">Setting up the code</h2>
-
- <p>To set up a Deltacloud core and the drivers, install the
- <a href="http://rubygems.org/gems/deltacloud-core">deltacloud-core</a> Ruby gem:</p>
-
- <pre><code># gem install deltacloud-core
</code></pre>
-
- <p>RPM package will be available soon.</p>
-
- <h2 id="h2">Launch the server</h2>
-
- <p>The server is launched with the <code>deltacloudd</code> command and pass it the name
- of the driver you want to use:</p>
-
- <pre><code>$ deltacloudd -i mock
</code></pre>
-
- <p>This will start a webserver running the mock driver on
- <code>http://localhost:3001/api</code>; you can simply browse to that URL to get a
- pretty view of the objects the driver deals with.</p>
-
- <h3 id="h2_1">EC2 Driver</h3>
+ <h3 id="h4_1">EC2 Driver</h3>
<p>For the Amazon EC2 you need to install the <code>amazon-ec2</code> Ruby gem:</p>
@@ -373,7 +408,7 @@
<p>These credentials may be found on the <a href="http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key">Access Identifiers</a>
page at Amazon AWS.</p>
- <h3 id="h2_2">RHEV-M Driver</h3>
+ <h3 id="h4_2">RHEV-M Driver</h3>
<p>The RHEV-M driver needs to be installed on a Windows machine which has the
RHEV-M Powershell API installed and configured. Assuming the directory
@@ -386,18 +421,18 @@
the RHEVM.dll.config file which is referenced from the profile.ps1
file located in My Documents/WindowsPowershell directory</p>
- <h3 id="h2_3">Rackspace Driver</h3>
+ <h3 id="h4_3">Rackspace Driver</h3>
<p>When using the Rackspace-cloud driver (Rackspace cloud used to be called
"Mosso") - the password in a HTTP 401 challenge should be your API key, NOT
your rackspace account password. (you can get the API-key, or generate a
new one, from the rackspace console).</p>
- <h3 id="h2_4">RimuHosting</h3>
+ <h3 id="h4_4">RimuHosting</h3>
<p>Further details coming soon.</p>
- <h3 id="h2_5">OpenNebula</h3>
+ <h3 id="h4_5">OpenNebula</h3>
<p>When using the <a href="http://www.opennebula.org/">OpenNebula</a> driver, the
credentials passed in response to the HTTP 401 authentication challenge
--
1.7.4
Re: Make drivers a toplevel collection
Posted by Michal Fojtik <mf...@redhat.com>.
On Mar 29, 2011, at 1:41 AM, lutter@redhat.com wrote:
> We've had an XML representation of drivers supported by the server as a
> one-off page for a while now. In keeping with HATEAOS, the list of drivers
> should be reachable through the main API entry point.
>
> To make that possible, I turned drivers into their own toplevel
> collection. I also changed the XML format for a driver to emphasize the
> list of possible provider values more. For the EC2 driver the XML now is:
>
> <driver href="http://localhost:3001/api/drivers/ec2" id="ec2">
> <name>EC2</name>
>
> <provider id="us-west-1">
> <entrypoint kind="s3">s3-us-west-1.amazonaws.com</entrypoint>
> <entrypoint kind="elb">elasticloadbalancing.us-west-1.amazonaws.com</entrypoint>
> <entrypoint kind="ec2">ec2.us-west-1.amazonaws.com</entrypoint>
> </provider>
>
> .. similar provider tags for the other regions ..
> </driver>
It makes perfect sense to me to turn it to top-level entrypoints.
Review notes:
- Applied cleanely, 3/3 gave me some trailing whitespace warnings
- Test::Unit output (rake test):
1) Failure:
test_it_expose_available_drivers(DeltacloudUnitTest::ApiTest)
[/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/expectations/fail_with.rb:41:in `fail_with'
/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/matchers/operator_matcher.rb:39:in `fail_with_message'
/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/matchers/operator_matcher.rb:63:in `__delegate_operator'
/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/matchers/operator_matcher.rb:51:in `eval_match'
/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/matchers/operator_matcher.rb:29:in `>'
./tests/drivers/mock/api_test.rb:79:in `test_it_expose_available_drivers']:
expected: > 0,
got: 0
2) Failure:
test_it_expose_ec2_driver_entrypoints(DeltacloudUnitTest::ApiTest)
[/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/expectations/fail_with.rb:41:in `fail_with'
/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/matchers/operator_matcher.rb:39:in `fail_with_message'
/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/matchers/operator_matcher.rb:63:in `__delegate_operator'
/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/matchers/operator_matcher.rb:51:in `eval_match'
/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/lib/spec/matchers/operator_matcher.rb:29:in `>'
./tests/drivers/mock/api_test.rb:86:in `test_it_expose_ec2_driver_entrypoints']:
expected: > 0,
got: 0
Seems like those tests need to be updated to this.
- Cucumber gave me 2 failures, related to top failures. Could you please include a fix for this?
- Functionality:
* http://localhost:3001/api/drivers/opennebula -> missing HAML template (HTML)
* Could you please also include JSON support for this collection?
-- Michal
------------------------------------------------------
Michal Fojtik, mfojtik@redhat.com
Deltacloud API: http://deltacloud.org
[PATCH 1/3] Rabbit: add notion of a 'global' collection
Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>
Global collections are supported by every driver
---
server/lib/sinatra/rabbit.rb | 17 +++++++++++++++--
1 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/server/lib/sinatra/rabbit.rb b/server/lib/sinatra/rabbit.rb
index a465ed6..8be2b8b 100644
--- a/server/lib/sinatra/rabbit.rb
+++ b/server/lib/sinatra/rabbit.rb
@@ -179,6 +179,7 @@ module Sinatra
@name = name
@description = ""
@operations = {}
+ @global = false
instance_eval(&block) if block_given?
generate_documentation
generate_head
@@ -193,6 +194,18 @@ module Sinatra
@description = text
end
+ # Mark this collection as global, i.e. independent of any specific
+ # driver
+ def global!
+ @global = true
+ end
+
+ # Return +true+ if this collection is global, i.e. independent of any
+ # specific driver
+ def global?
+ @global
+ end
+
def generate_head
current_collection = self
::Sinatra::Application.head("/api/#{name}") do
@@ -261,7 +274,7 @@ module Sinatra
end
def check_supported(driver)
- unless driver.has_collection?(@name)
+ unless global? || driver.has_collection?(@name)
raise UnsupportedCollectionException,
"Collection #{@name} not supported by this driver"
end
@@ -301,7 +314,7 @@ module Sinatra
def entry_points
collections.values.select { |coll|
- driver.has_collection?(coll.name)
+ coll.global? || driver.has_collection?(coll.name)
}.inject([]) do |m, coll|
url = url_for coll.operations[:index].path, :full
m << [ coll.name, url ]
--
1.7.4