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 2013/03/14 19:19:03 UTC

[13/15] git commit: CIMI: make ResourceMetadata work with the Model/Service split

CIMI: make ResourceMetadata work with the Model/Service split

Extension attributes now need to be mentioned twice: in the model class
they are declared like any other attribute. In the service class, resource
metadata can be added using

  metadata attr_name, :type => TYPE, :constraints => PROC


Project: http://git-wip-us.apache.org/repos/asf/deltacloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltacloud/commit/d974429b
Tree: http://git-wip-us.apache.org/repos/asf/deltacloud/tree/d974429b
Diff: http://git-wip-us.apache.org/repos/asf/deltacloud/diff/d974429b

Branch: refs/heads/master
Commit: d974429b062142740a24832c055874a4c709e718
Parents: 83cca11
Author: David Lutterkort <lu...@redhat.com>
Authored: Fri Mar 1 17:21:16 2013 -0800
Committer: David Lutterkort <lu...@redhat.com>
Committed: Wed Mar 13 17:28:13 2013 -0700

----------------------------------------------------------------------
 server/lib/cimi/models/cloud_entry_point.rb  |    4 +-
 server/lib/cimi/models/machine.rb            |    8 +-
 server/lib/cimi/models/machine_template.rb   |    3 +-
 server/lib/cimi/models/resource_metadata.rb  |   10 --
 server/lib/cimi/models/schema.rb             |    9 --
 server/lib/cimi/service.rb                   |   10 ++-
 server/lib/cimi/service/base.rb              |   58 +++++++++++++
 server/lib/cimi/service/cloud_entry_point.rb |    3 +
 server/lib/cimi/service/machine.rb           |    7 ++
 server/lib/cimi/service/machine_template.rb  |    4 +-
 server/lib/cimi/service/resource_metadata.rb |   92 +++------------------
 11 files changed, 98 insertions(+), 110 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/models/cloud_entry_point.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/cloud_entry_point.rb b/server/lib/cimi/models/cloud_entry_point.rb
index a016004..a1ec0a7 100644
--- a/server/lib/cimi/models/cloud_entry_point.rb
+++ b/server/lib/cimi/models/cloud_entry_point.rb
@@ -15,8 +15,8 @@
 
 class CIMI::Model::CloudEntryPoint < CIMI::Model::Base
 
-  resource_attr :driver, :required => true
-  resource_attr :provider, :required => true
+  text :driver, :required => true
+  text :provider, :required => true
 
   # All possible CIMI collections, in the order in which they should appear
   # in the CEP

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/models/machine.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine.rb b/server/lib/cimi/models/machine.rb
index 6990fb9..3d1369c 100644
--- a/server/lib/cimi/models/machine.rb
+++ b/server/lib/cimi/models/machine.rb
@@ -17,10 +17,10 @@ class CIMI::Model::Machine < CIMI::Model::Base
 
   acts_as_root_entity
 
-  resource_attr :realm, :required => false,
-    :constraints => lambda { |c| c.driver.realms(c.credentials).map { |r| r.id } }
-
-  resource_attr :machine_image, :required => false, :type => :href
+  # DC-specific Extension
+  text :realm, :required => false
+  # DC-specific extension
+  href :machine_image, :required => false
 
   text :state
   text :cpu

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/models/machine_template.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_template.rb b/server/lib/cimi/models/machine_template.rb
index 812ad15..68e865b 100644
--- a/server/lib/cimi/models/machine_template.rb
+++ b/server/lib/cimi/models/machine_template.rb
@@ -22,8 +22,7 @@ class CIMI::Model::MachineTemplate < CIMI::Model::Base
   ref :machine_image
   ref :credential
 
-  resource_attr :realm, :required => false,
-    :constraints => lambda { |c| c.driver.realms(c.credentials).map { |r| r.id }}
+  text :realm, :required => false
 
   array :volumes do
     scalar :href, :initial_location

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/models/resource_metadata.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/resource_metadata.rb b/server/lib/cimi/models/resource_metadata.rb
index 2c4ee08..0a2ab5d 100644
--- a/server/lib/cimi/models/resource_metadata.rb
+++ b/server/lib/cimi/models/resource_metadata.rb
@@ -51,14 +51,4 @@ class CIMI::Model::ResourceMetadata < CIMI::Model::Base
   array :operations do
     scalar :rel, :href
   end
-
-  def self.add_resource_attribute!(klass, name, opts={})
-    resource_attributes[klass.name] ||= {}
-    resource_attributes[klass.name][name] = opts
-  end
-
-  def self.resource_attributes
-    @resource_attributes ||= {}
-  end
-
 end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/models/schema.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index 9c27c6f..b6651a7 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -425,15 +425,6 @@ class CIMI::Model::Schema
   # +add_attributes!+ method
   module DSL
 
-    def resource_attr(name, opts={})
-      CIMI::Model::ResourceMetadata.add_resource_attribute!(self, name, opts)
-      if opts[:type]
-        send(opts[:type], name)
-      else
-        text name
-      end
-    end
-
     def href(*args)
       opts = args.extract_opts!
       args.each { |arg| struct(arg, opts) { scalar :href, :required => opts[:required] } }

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/service.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/service.rb b/server/lib/cimi/service.rb
index b05efbf..8176532 100644
--- a/server/lib/cimi/service.rb
+++ b/server/lib/cimi/service.rb
@@ -14,7 +14,15 @@
 # under the License.
 #
 
-module CIMI::Service; end
+module CIMI
+  module Service
+    def self.root_entities
+      CIMI::Model::root_entities.map do |m|
+        CIMI::Service.const_get(m.name.split('::').last)
+      end
+    end
+  end
+end
 
 require_relative './models'
 require_relative './../db/provider'

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/service/base.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/service/base.rb b/server/lib/cimi/service/base.rb
index fa845d0..b829e6a 100644
--- a/server/lib/cimi/service/base.rb
+++ b/server/lib/cimi/service/base.rb
@@ -136,6 +136,64 @@ module CIMI::Service
       end
     end
 
+    #
+    # Resource metadata
+    #
+    METADATA_TYPES = [ 'text', 'URI', 'string', 'boolean' ]
+
+    # A hash of the attributes that need to be mentioned in the given
+    # context
+    def self.resource_attributes(context)
+      metadata.keys.map do |k|
+        a = model_class.schema.attributes.find { |a| a.name == k }
+        raise "No attribute named #{k} defined" unless a
+        constr = metadata[k][:constraints].call(context)
+        {
+          :name => a.name,
+          :namespace => "http://deltacloud.org/cimi/#{model_name}/#{a.name}",
+          :type => metadata[k][:type],
+          :required => a.required? ? 'true' : 'false',
+          :constraints => constr.map { |v| { :value => v } }
+        }
+      end
+    end
+
+    def self.resource_capabilities(context)
+      cimi_object = model_name.to_s.pluralize.to_sym
+      driver_class = context.driver.class
+      (driver_class.features[cimi_object] || []).map do |cur|
+        feat = CIMI::FakeCollection.feature(cur)
+        values = driver_class.constraints[cimi_object][feat.name][:values] || []
+        { :name => feat.name.to_s.camelize,
+          :uri => CMWG_NAMESPACE+"/capability/#{cimi_object.to_s.camelize.singularize}/#{feat.name.to_s.camelize}",
+          :description => feat.description,
+          :value => values.join(",")
+        }
+      end
+    end
+
+    # Define the metadata for an attribute; +opts+ must be a Hash that can
+    # contain the following entries:
+    #   :type : one of METADATA_TYPES
+    #   :constraints : a proc that is passed the current context and
+    #                  must return a list of values
+    def self.metadata(attr_name = nil, opts = nil)
+      @metadata ||= {}
+      return @metadata if attr_name.nil? && opts.nil?
+
+      opts[:type] ||= 'text'
+      opts[:type] = opts[:type].to_s
+      opts[:constraints] ||= lambda { |_| [] }
+      unless METADATA_TYPES.include?(opts[:type])
+        raise "Metadata type must be one of #{METADATA_TYPES.join(",")}"
+      end
+      metadata[attr_name] = opts
+    end
+
+    #
+    # Database interactions
+    #
+
     # Save the common attributes name, description, and properties to the
     # database
     def save

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/service/cloud_entry_point.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/service/cloud_entry_point.rb b/server/lib/cimi/service/cloud_entry_point.rb
index 5029e12..9491e3d 100644
--- a/server/lib/cimi/service/cloud_entry_point.rb
+++ b/server/lib/cimi/service/cloud_entry_point.rb
@@ -15,6 +15,9 @@
 
 class CIMI::Service::CloudEntryPoint < CIMI::Service::Base
 
+  metadata :driver, :type => 'text'
+  metadata :provider, :type => 'text'
+
   def self.create(context)
     self.new(context, :values => entities(context).merge({
       :name => context.driver.name,

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/service/machine.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/service/machine.rb b/server/lib/cimi/service/machine.rb
index 7112486..f347cda 100644
--- a/server/lib/cimi/service/machine.rb
+++ b/server/lib/cimi/service/machine.rb
@@ -15,6 +15,13 @@
 
 class CIMI::Service::Machine < CIMI::Service::Base
 
+  metadata :realm,
+    :constraints => lambda { |c|
+      c.driver.realms(c.credentials).map { |r| r.id }
+  }
+
+  metadata :machine_image, :type => 'URI'
+
   def self.find(id, context)
     instances = []
     if id == :all

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/service/machine_template.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/service/machine_template.rb b/server/lib/cimi/service/machine_template.rb
index e790e89..4a3cd4e 100644
--- a/server/lib/cimi/service/machine_template.rb
+++ b/server/lib/cimi/service/machine_template.rb
@@ -15,9 +15,7 @@
 
 class CIMI::Service::MachineTemplate < CIMI::Service::Base
 
-  def initialize(ctx, opts)
-    super
-  end
+  metadata :realm, :constraints => lambda { |c| c.driver.realms(c.credentials).map { |r| r.id }}
 
   class << self
     def find(id, context)

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/d974429b/server/lib/cimi/service/resource_metadata.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/service/resource_metadata.rb b/server/lib/cimi/service/resource_metadata.rb
index 23924fb..3a8f09f 100644
--- a/server/lib/cimi/service/resource_metadata.rb
+++ b/server/lib/cimi/service/resource_metadata.rb
@@ -15,96 +15,30 @@
 
 class CIMI::Service::ResourceMetadata < CIMI::Service::Base
 
-  def initialize(ctx, opts)
-    super
-  end
-
   def self.find(id, context)
     if id == :all
-      resource_metadata = []
-      CIMI::Model.root_entities.each do |resource_class|
-        meta = resource_metadata_for(resource_class, context)
-        resource_metadata << meta unless none_defined(meta)
-      end
-      return resource_metadata
+      CIMI::Service.root_entities.map do |svc_class|
+        resource_metadata_for(svc_class, context)
+      end.reject { |metadata| metadata.none_defined? }
     else
-      resource_class = CIMI::Model.const_get("#{id.camelize}")
-      resource_metadata_for(resource_class, context)
+      svc_class = CIMI::Service.const_get("#{id.camelize}")
+      resource_metadata_for(svc_class, context)
     end
   end
 
-  def self.resource_metadata_for(resource_class, context)
-    attributes = rm_attributes_for(resource_class, context)
-    capabilities = rm_capabilities_for(resource_class, context)
-    actions = rm_actions_for(resource_class, context)
-    cimi_resource = resource_class.name.split("::").last
+  def self.resource_metadata_for(svc_class, context)
+    cimi_resource = svc_class.name.split("::").last
     self.new(context, :values => {
       :id => context.resource_metadata_url(cimi_resource.underscore),
       :name => cimi_resource,
-      :type_uri => resource_class.resource_uri,
-      :attributes => attributes,
-      :capabilities => capabilities,
-      :actions => actions
+      :type_uri => svc_class.model_class.resource_uri,
+      :attributes => svc_class.resource_attributes(context),
+      :capabilities => svc_class.resource_capabilities(context),
+      :actions => []
     })
   end
 
-  private
-
-  def self.rm_attributes_for(resource_class, context)
-    return [] if resource_attributes[resource_class.name].nil?
-    resource_attributes[resource_class.name].map do |attr_name, attr_def|
-      if attr_def.has_key? :constraints
-        constraints = attr_def[:constraints].call(context)
-      else
-        constraints = []
-      end
-      {
-        :name => attr_name.to_s,
-        # TODO: We need to make this URI return description of this 'non-CIMI'
-        # attribute
-        :namespace => "http://deltacloud.org/cimi/#{resource_class.name.split('::').last}/#{attr_name}",
-        :type => translate_attr_type(attr_def[:type]),
-        :required => attr_def[:required] ? 'true' : 'false',
-        :constraints => constraints.map { |v| { :value => v }}
-      }
-    end
-  end
-
-  # FIXME: This method is srsly a nightmare ;-)
-  #
-  def self.rm_capabilities_for(resource_class,context)
-    cimi_object = resource_class.name.split("::").last.underscore.pluralize.to_sym
-    (context.driver.class.features[cimi_object] || []).inject([]) do |res, cur|
-      feat = CIMI::FakeCollection.feature(cur)
-      values = (context.driver.class.constraints[cimi_object][feat.name][:values] || []).inject([]) do |vals, val|
-        vals <<  val
-        vals
-      end
-      res << {:name => feat.name.to_s.camelize,
-              :uri => CMWG_NAMESPACE+"/capability/#{cimi_object.to_s.camelize.singularize}/#{feat.name.to_s.camelize}",
-      :description => feat.description,
-      :value => values.join(",") }
-      res
-    end
-  end
-
-  def self.rm_actions_for(resource_class, context)
-    []
-  end
-
-  def self.translate_attr_type(type)
-    case type
-      when :href then 'URI'
-      when :text then 'string'
-      when :boolean then 'boolean'
-      else 'text'
-    end
-  end
-
-  def self.none_defined(metadata)
-    return true if metadata.capabilities.empty? && metadata.capabilities.empty? && metadata.attributes.empty?
-    return false
+  def none_defined?
+    capabilities.empty? && attributes.empty?
   end
-
-
 end