You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by tc...@redhat.com on 2010/12/03 17:44:42 UTC
[PATCH core] Drivers now declare the capabilities they provide by implementing methods for each collection.
From: Tobias Crawley <tc...@redhat.com>
This patch makes the with_capability feature in rabbit actually work - before
this, all drivers would appear to provide most capabilities, since the check
was a simple respond_to?, and most capabilities were defined in the base_driver,
and overridden by the drivers. With this change, those empty definitions are
removed from the base_driver.
The next step is to expose the available capabilities with the entry_points.
I've started on that, but it introduces top level api changes, so I'll send
a separate message to the list for discussion.
Toby
---
server/lib/deltacloud/backend_capability.rb | 16 +++-
server/lib/deltacloud/base_driver/base_driver.rb | 135 ++++++++++------------
server/lib/deltacloud/base_driver/features.rb | 6 +
server/lib/deltacloud/drivers/ec2/ec2_driver.rb | 4 -
4 files changed, 83 insertions(+), 78 deletions(-)
diff --git a/server/lib/deltacloud/backend_capability.rb b/server/lib/deltacloud/backend_capability.rb
index bec8714..5594550 100644
--- a/server/lib/deltacloud/backend_capability.rb
+++ b/server/lib/deltacloud/backend_capability.rb
@@ -2,6 +2,7 @@ module Deltacloud::BackendCapability
class Failure < StandardError
attr_reader :capability
+
def initialize(capability, msg='')
super(msg)
@capability = capability
@@ -9,13 +10,26 @@ module Deltacloud::BackendCapability
end
attr_reader :capability
+
def with_capability(capability)
@capability = capability
end
+ def has_capability?(backend)
+ !capability or backend.has_capability?(capability)
+ end
+
def check_capability(backend)
- if capability and !backend.respond_to?(capability)
+ if !has_capability?(backend)
raise Failure.new(capability, "#{capability} capability not supported by backend #{backend.class.name}")
end
end
+
+ module Helpers
+ def operations_for_collection(collection)
+ collections[collection].operations.values.select { |op| op.has_capability?(driver) }
+ end
+ end
+
+ helpers Helpers
end
diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
index 4419359..7815eb4 100644
--- a/server/lib/deltacloud/base_driver/base_driver.rb
+++ b/server/lib/deltacloud/base_driver/base_driver.rb
@@ -42,7 +42,7 @@ module Deltacloud
end
class BaseDriver
-
+
def self.define_hardware_profile(name,&block)
@hardware_profiles ||= []
hw_profile = @hardware_profiles.find{|e| e.name == name}
@@ -126,100 +126,90 @@ module Deltacloud
actions
end
+ ## Capabilities
+ # The rabbit dsl supports declaring a capability that is required
+ # in the backend driver for the call to succeed. A driver can
+ # provide a capability by implementing the method with the same
+ # name as the capability. Below is a list of the capabilities as
+ # the expected method signatures.
+ #
+ # Following the capability list are the resource member show
+ # methods. They each require that the corresponding collection
+ # method be defined
+ #
+ # TODO: standardize all of these to the same signature (credentials, opts)
+ #
+ # def realms(credentials, opts=nil)
+ #
+ # def images(credentials, ops)
+ #
+ # def instances(credentials, ops)
+ # def create_instance(credentials, image_id, opts)
+ # def start_instance(credentials, id)
+ # def stop_instance(credentials, id)
+ # def reboot_instance(credentials, id)
+ #
+ # def storage_volumes(credentials, ops)
+ #
+ # def storage_snapshots(credentials, ops)
+ #
+ # def buckets(credentials, opts = nil)
+ # def create_bucket(credentials, name, opts=nil)
+ # def delete_bucket(credentials, name, opts=nil)
+ #
+ # def blobs(credentials, opts = nil)
+ # def blob_data(credentials, bucket_id, blob_id, opts)
+ # def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
+ # def delete_blob(credentials, bucket_id, blob_id, opts=nil)
+ #
+ # def keys(credentials, opts)
+ # def create_key(credentials, opts)
+ # def destroy_key(credentials, opts)
+
def realm(credentials, opts)
- realms = realms(credentials, opts)
- return realms.first unless realms.empty?
- nil
- end
-
- def realms(credentials, opts=nil)
- []
+ realms = realms(credentials, opts).first if has_capability?(:realms)
end
def image(credentials, opts)
- images = images(credentials, opts)
- return images.first unless images.empty?
- nil
- end
-
- def images(credentials, ops)
- []
+ images(credentials, opts).first if has_capability?(:images)
end
def instance(credentials, opts)
- instances = instances(credentials, opts)
- return instances.first unless instances.empty?
- nil
- end
-
- def instances(credentials, ops)
- []
- end
-
- def create_instance(credentials, image_id, opts)
- end
- def start_instance(credentials, id)
- end
- def stop_instance(credentials, id)
- end
- def reboot_instance(credentials, id)
+ instances(credentials, opts).first if has_capability?(:instances)
end
def storage_volume(credentials, opts)
- volumes = storage_volumes(credentials, opts)
- return volumes.first unless volumes.empty?
- nil
- end
-
- def storage_volumes(credentials, ops)
- []
+ storage_volumes(credentials, opts).first if has_capability?(:storage_volumes)
end
def storage_snapshot(credentials, opts)
- snapshots = storage_snapshots(credentials, opts)
- return snapshots.first unless snapshots.empty?
- nil
- end
-
- def storage_snapshots(credentials, ops)
- []
- end
-
- def buckets(credentials, opts = nil)
- #list of buckets belonging to account
- []
+ storage_snapshots(credentials, opts).first if has_capability?(:storage_snapshots)
end
def bucket(credentials, opts = nil)
- #list of objects within bucket
- list = buckets(credentials, opts)
- return list.first unless list.empty?
- nil
- end
-
- def create_bucket(credentials, name, opts=nil)
- end
-
- def delete_bucket(credentials, name, opts=nil)
+ #list of objects within bucket
+ buckets(credentials, opts).first if has_capability?(:buckets)
end
-
- def blobs(credentials, opts = nil)
- []
- end
-
+
def blob(credentials, opts = nil)
- list = blobs(credentials, opts)
- return list.first unless list.empty?
+ blobs(credentials, opts).first if has_capability?(:blobs)
end
- def blob_data(credentials, bucket_id, blob_id, opts)
+ def key(credentials, opts=nil)
+ keys(credentials, opts).first if has_capability?(:keys)
end
- def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
- end
+ MEMBER_SHOW_METHODS =
+ [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key ]
- def delete_blob(credentials, bucket_id, blob_id, opts=nil)
+ def has_capability?(capability)
+ if MEMBER_SHOW_METHODS.include?(capability.to_sym)
+ has_capability?(capability.to_s.pluralize)
+ else
+ respond_to?(capability)
+ end
end
+
def filter_on(collection, attribute, opts)
return collection if opts.nil?
@@ -237,8 +227,7 @@ module Deltacloud
end
def has_collection?(collection)
- return true if self.supported_collections.include?(collection)
- return false
+ supported_collections.include?(collection)
end
def catched_exceptions_list
diff --git a/server/lib/deltacloud/base_driver/features.rb b/server/lib/deltacloud/base_driver/features.rb
index de055de..f20f635 100644
--- a/server/lib/deltacloud/base_driver/features.rb
+++ b/server/lib/deltacloud/base_driver/features.rb
@@ -117,6 +117,12 @@ module Deltacloud
self.class.features[collection] || []
end
+ def features_for_operation(collection, operation)
+ features(collection).select do |f|
+ f.operations.detect { |o| o.name == operation }
+ end
+ end
+
#
# Declaration of optional features
#
diff --git a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
index d38f8f7..9fc0726 100644
--- a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
+++ b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
@@ -284,10 +284,6 @@ class EC2Driver < Deltacloud::BaseDriver
snapshots
end
- def key(credentials, opts=nil)
- keys(credentials, opts).first
- end
-
def keys(credentials, opts=nil)
ec2 = new_client( credentials )
opts[:key_name] = opts[:id] if opts and opts[:id]
--
1.7.3.2
Re: [PATCH core] Drivers now declare the capabilities they provide
by implementing methods for each collection.
Posted by Michal Fojtik <mf...@redhat.com>.
On 03/12/10 11:44 -0500, tcrawley@redhat.com wrote:
>From: Tobias Crawley <tc...@redhat.com>
>
>This patch makes the with_capability feature in rabbit actually work - before
>this, all drivers would appear to provide most capabilities, since the check
>was a simple respond_to?, and most capabilities were defined in the base_driver,
>and overridden by the drivers. With this change, those empty definitions are
>removed from the base_driver.
>
>The next step is to expose the available capabilities with the entry_points.
>I've started on that, but it introduces top level api changes, so I'll send
>a separate message to the list for discussion.
Works perfecly, applied cleanely on latest master.
Our test suites are perfectly happy with that as well.
This is a great addition to API Tobi, thanks for this work.
ACK && push.
-- Michal
>
>Toby
>
>---
> server/lib/deltacloud/backend_capability.rb | 16 +++-
> server/lib/deltacloud/base_driver/base_driver.rb | 135 ++++++++++------------
> server/lib/deltacloud/base_driver/features.rb | 6 +
> server/lib/deltacloud/drivers/ec2/ec2_driver.rb | 4 -
> 4 files changed, 83 insertions(+), 78 deletions(-)
>
>diff --git a/server/lib/deltacloud/backend_capability.rb b/server/lib/deltacloud/backend_capability.rb
>index bec8714..5594550 100644
>--- a/server/lib/deltacloud/backend_capability.rb
>+++ b/server/lib/deltacloud/backend_capability.rb
>@@ -2,6 +2,7 @@ module Deltacloud::BackendCapability
>
> class Failure < StandardError
> attr_reader :capability
>+
> def initialize(capability, msg='')
> super(msg)
> @capability = capability
>@@ -9,13 +10,26 @@ module Deltacloud::BackendCapability
> end
>
> attr_reader :capability
>+
> def with_capability(capability)
> @capability = capability
> end
>
>+ def has_capability?(backend)
>+ !capability or backend.has_capability?(capability)
>+ end
>+
> def check_capability(backend)
>- if capability and !backend.respond_to?(capability)
>+ if !has_capability?(backend)
> raise Failure.new(capability, "#{capability} capability not supported by backend #{backend.class.name}")
> end
> end
>+
>+ module Helpers
>+ def operations_for_collection(collection)
>+ collections[collection].operations.values.select { |op| op.has_capability?(driver) }
>+ end
>+ end
>+
>+ helpers Helpers
> end
>diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
>index 4419359..7815eb4 100644
>--- a/server/lib/deltacloud/base_driver/base_driver.rb
>+++ b/server/lib/deltacloud/base_driver/base_driver.rb
>@@ -42,7 +42,7 @@ module Deltacloud
> end
>
> class BaseDriver
>-
>+
> def self.define_hardware_profile(name,&block)
> @hardware_profiles ||= []
> hw_profile = @hardware_profiles.find{|e| e.name == name}
>@@ -126,100 +126,90 @@ module Deltacloud
> actions
> end
>
>+ ## Capabilities
>+ # The rabbit dsl supports declaring a capability that is required
>+ # in the backend driver for the call to succeed. A driver can
>+ # provide a capability by implementing the method with the same
>+ # name as the capability. Below is a list of the capabilities as
>+ # the expected method signatures.
>+ #
>+ # Following the capability list are the resource member show
>+ # methods. They each require that the corresponding collection
>+ # method be defined
>+ #
>+ # TODO: standardize all of these to the same signature (credentials, opts)
>+ #
>+ # def realms(credentials, opts=nil)
>+ #
>+ # def images(credentials, ops)
>+ #
>+ # def instances(credentials, ops)
>+ # def create_instance(credentials, image_id, opts)
>+ # def start_instance(credentials, id)
>+ # def stop_instance(credentials, id)
>+ # def reboot_instance(credentials, id)
>+ #
>+ # def storage_volumes(credentials, ops)
>+ #
>+ # def storage_snapshots(credentials, ops)
>+ #
>+ # def buckets(credentials, opts = nil)
>+ # def create_bucket(credentials, name, opts=nil)
>+ # def delete_bucket(credentials, name, opts=nil)
>+ #
>+ # def blobs(credentials, opts = nil)
>+ # def blob_data(credentials, bucket_id, blob_id, opts)
>+ # def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
>+ # def delete_blob(credentials, bucket_id, blob_id, opts=nil)
>+ #
>+ # def keys(credentials, opts)
>+ # def create_key(credentials, opts)
>+ # def destroy_key(credentials, opts)
>+
> def realm(credentials, opts)
>- realms = realms(credentials, opts)
>- return realms.first unless realms.empty?
>- nil
>- end
>-
>- def realms(credentials, opts=nil)
>- []
>+ realms = realms(credentials, opts).first if has_capability?(:realms)
> end
>
> def image(credentials, opts)
>- images = images(credentials, opts)
>- return images.first unless images.empty?
>- nil
>- end
>-
>- def images(credentials, ops)
>- []
>+ images(credentials, opts).first if has_capability?(:images)
> end
>
> def instance(credentials, opts)
>- instances = instances(credentials, opts)
>- return instances.first unless instances.empty?
>- nil
>- end
>-
>- def instances(credentials, ops)
>- []
>- end
>-
>- def create_instance(credentials, image_id, opts)
>- end
>- def start_instance(credentials, id)
>- end
>- def stop_instance(credentials, id)
>- end
>- def reboot_instance(credentials, id)
>+ instances(credentials, opts).first if has_capability?(:instances)
> end
>
> def storage_volume(credentials, opts)
>- volumes = storage_volumes(credentials, opts)
>- return volumes.first unless volumes.empty?
>- nil
>- end
>-
>- def storage_volumes(credentials, ops)
>- []
>+ storage_volumes(credentials, opts).first if has_capability?(:storage_volumes)
> end
>
> def storage_snapshot(credentials, opts)
>- snapshots = storage_snapshots(credentials, opts)
>- return snapshots.first unless snapshots.empty?
>- nil
>- end
>-
>- def storage_snapshots(credentials, ops)
>- []
>- end
>-
>- def buckets(credentials, opts = nil)
>- #list of buckets belonging to account
>- []
>+ storage_snapshots(credentials, opts).first if has_capability?(:storage_snapshots)
> end
>
> def bucket(credentials, opts = nil)
>- #list of objects within bucket
>- list = buckets(credentials, opts)
>- return list.first unless list.empty?
>- nil
>- end
>-
>- def create_bucket(credentials, name, opts=nil)
>- end
>-
>- def delete_bucket(credentials, name, opts=nil)
>+ #list of objects within bucket
>+ buckets(credentials, opts).first if has_capability?(:buckets)
> end
>-
>- def blobs(credentials, opts = nil)
>- []
>- end
>-
>+
> def blob(credentials, opts = nil)
>- list = blobs(credentials, opts)
>- return list.first unless list.empty?
>+ blobs(credentials, opts).first if has_capability?(:blobs)
> end
>
>- def blob_data(credentials, bucket_id, blob_id, opts)
>+ def key(credentials, opts=nil)
>+ keys(credentials, opts).first if has_capability?(:keys)
> end
>
>- def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
>- end
>+ MEMBER_SHOW_METHODS =
>+ [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key ]
>
>- def delete_blob(credentials, bucket_id, blob_id, opts=nil)
>+ def has_capability?(capability)
>+ if MEMBER_SHOW_METHODS.include?(capability.to_sym)
>+ has_capability?(capability.to_s.pluralize)
>+ else
>+ respond_to?(capability)
>+ end
> end
>+
>
> def filter_on(collection, attribute, opts)
> return collection if opts.nil?
>@@ -237,8 +227,7 @@ module Deltacloud
> end
>
> def has_collection?(collection)
>- return true if self.supported_collections.include?(collection)
>- return false
>+ supported_collections.include?(collection)
> end
>
> def catched_exceptions_list
>diff --git a/server/lib/deltacloud/base_driver/features.rb b/server/lib/deltacloud/base_driver/features.rb
>index de055de..f20f635 100644
>--- a/server/lib/deltacloud/base_driver/features.rb
>+++ b/server/lib/deltacloud/base_driver/features.rb
>@@ -117,6 +117,12 @@ module Deltacloud
> self.class.features[collection] || []
> end
>
>+ def features_for_operation(collection, operation)
>+ features(collection).select do |f|
>+ f.operations.detect { |o| o.name == operation }
>+ end
>+ end
>+
> #
> # Declaration of optional features
> #
>diff --git a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
>index d38f8f7..9fc0726 100644
>--- a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
>+++ b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
>@@ -284,10 +284,6 @@ class EC2Driver < Deltacloud::BaseDriver
> snapshots
> end
>
>- def key(credentials, opts=nil)
>- keys(credentials, opts).first
>- end
>-
> def keys(credentials, opts=nil)
> ec2 = new_client( credentials )
> opts[:key_name] = opts[:id] if opts and opts[:id]
>--
>1.7.3.2
>
--
--------------------------------------------------------
Michal Fojtik, mfojtik@redhat.com
Deltacloud API: http://deltacloud.org
--------------------------------------------------------