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 2013/03/14 01:33:32 UTC

RFC: Separate CIMI (de)serialization from server functionality (rev 3)

This is the third take on splitting server-side functionality out of our
models. As in previous attempts, CIMI::Model is now solely concerned with
(se)serialization, whereas CIMI::Service does all the actual server-side
functionality.

FWIW, the unit and blackbox tests all pass for me with this patch series
...

Also recorded as http://tracker.deltacloud.org/set/389

David

[PATCH 08/14] CIMI: Migrated service methods from CIMI::Model to CIMI::Service

Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>

---
 server/lib/cimi/models/action.rb                   |   4 -
 server/lib/cimi/models/address.rb                  |  38 -------
 server/lib/cimi/models/address_create.rb           |  31 ------
 server/lib/cimi/models/address_template.rb         |  47 ---------
 server/lib/cimi/models/address_template_create.rb  |  16 ---
 server/lib/cimi/models/cloud_entry_point.rb        |  28 ------
 server/lib/cimi/models/credential.rb               |  34 -------
 server/lib/cimi/models/credential_create.rb        |  26 -----
 server/lib/cimi/models/credential_template.rb      |   2 -
 server/lib/cimi/models/disk.rb                     |  56 -----------
 server/lib/cimi/models/forwarding_group.rb         |   8 --
 .../lib/cimi/models/forwarding_group_template.rb   |   8 --
 server/lib/cimi/models/machine_configuration.rb    |  31 ------
 server/lib/cimi/models/machine_create.rb           |  30 +-----
 server/lib/cimi/models/machine_image_create.rb     |  19 ----
 server/lib/cimi/models/machine_template.rb         |  35 -------
 server/lib/cimi/models/machine_template_create.rb  |  12 ---
 server/lib/cimi/models/machine_volume.rb           |  65 ------------
 server/lib/cimi/models/network.rb                  |  32 ------
 server/lib/cimi/models/network_configuration.rb    |  15 ---
 server/lib/cimi/models/network_create.rb           |  23 -----
 server/lib/cimi/models/network_port.rb             |  73 --------------
 .../lib/cimi/models/network_port_configuration.rb  |   8 --
 server/lib/cimi/models/network_port_template.rb    |   8 --
 server/lib/cimi/models/network_template.rb         |  10 --
 server/lib/cimi/models/resource_metadata.rb        |  90 +----------------
 server/lib/cimi/models/system.rb                   |  52 +++-------
 server/lib/cimi/models/system_template.rb          |  44 +++------
 server/lib/cimi/models/volume.rb                   |  59 -----------
 server/lib/cimi/models/volume_configuration.rb     |  63 ------------
 server/lib/cimi/models/volume_create.rb            |  38 -------
 server/lib/cimi/models/volume_image.rb             |  30 ------
 server/lib/cimi/models/volume_image_create.rb      |  25 -----
 server/lib/cimi/models/volume_template.rb          |  41 --------
 server/lib/cimi/models/volume_template_create.rb   |  12 ---
 server/lib/cimi/service.rb                         |  35 +++++++
 server/lib/cimi/service/action.rb                  |  21 ++++
 server/lib/cimi/service/address.rb                 |  56 +++++++++++
 server/lib/cimi/service/address_create.rb          |  45 +++++++++
 server/lib/cimi/service/address_template.rb        |  71 +++++++++++++
 server/lib/cimi/service/address_template_create.rb |  34 +++++++
 server/lib/cimi/service/cloud_entry_point.rb       |  46 +++++++++
 server/lib/cimi/service/credential.rb              |  52 ++++++++++
 server/lib/cimi/service/credential_create.rb       |  38 +++++++
 server/lib/cimi/service/credential_template.rb     |  20 ++++
 server/lib/cimi/service/disk.rb                    |  80 +++++++++++++++
 server/lib/cimi/service/forwarding_group.rb        |  26 +++++
 .../lib/cimi/service/forwarding_group_template.rb  |  26 +++++
 server/lib/cimi/service/machine.rb                 |  14 +--
 server/lib/cimi/service/machine_configuration.rb   |  54 ++++++++++
 server/lib/cimi/service/machine_create.rb          |  49 +++++++++
 server/lib/cimi/service/machine_image.rb           |   6 +-
 server/lib/cimi/service/machine_image_create.rb    |  35 +++++++
 server/lib/cimi/service/machine_template.rb        |  61 ++++++++++++
 server/lib/cimi/service/machine_template_create.rb |  29 ++++++
 server/lib/cimi/service/machine_volume.rb          |  74 ++++++++++++++
 server/lib/cimi/service/network.rb                 |  51 ++++++++++
 server/lib/cimi/service/network_configuration.rb   |  36 +++++++
 server/lib/cimi/service/network_create.rb          |  39 ++++++++
 server/lib/cimi/service/network_port.rb            |  97 ++++++++++++++++++
 .../lib/cimi/service/network_port_configuration.rb |  26 +++++
 server/lib/cimi/service/network_port_template.rb   |  26 +++++
 server/lib/cimi/service/network_template.rb        |  28 ++++++
 server/lib/cimi/service/resource_metadata.rb       | 110 +++++++++++++++++++++
 server/lib/cimi/service/system.rb                  |  45 +++++++++
 server/lib/cimi/service/system_template.rb         |  32 ++++++
 server/lib/cimi/service/volume.rb                  |  81 +++++++++++++++
 server/lib/cimi/service/volume_configuration.rb    |  92 +++++++++++++++++
 server/lib/cimi/service/volume_create.rb           |  47 +++++++++
 server/lib/cimi/service/volume_image.rb            |  44 +++++++++
 server/lib/cimi/service/volume_image_create.rb     |  42 ++++++++
 server/lib/cimi/service/volume_template.rb         |  61 ++++++++++++
 server/lib/cimi/service/volume_template_create.rb  |  29 ++++++
 73 files changed, 1779 insertions(+), 1092 deletions(-)
 create mode 100644 server/lib/cimi/service/action.rb
 create mode 100644 server/lib/cimi/service/address.rb
 create mode 100644 server/lib/cimi/service/address_create.rb
 create mode 100644 server/lib/cimi/service/address_template.rb
 create mode 100644 server/lib/cimi/service/address_template_create.rb
 create mode 100644 server/lib/cimi/service/cloud_entry_point.rb
 create mode 100644 server/lib/cimi/service/credential.rb
 create mode 100644 server/lib/cimi/service/credential_create.rb
 create mode 100644 server/lib/cimi/service/credential_template.rb
 create mode 100644 server/lib/cimi/service/disk.rb
 create mode 100644 server/lib/cimi/service/forwarding_group.rb
 create mode 100644 server/lib/cimi/service/forwarding_group_template.rb
 create mode 100644 server/lib/cimi/service/machine_configuration.rb
 create mode 100644 server/lib/cimi/service/machine_create.rb
 create mode 100644 server/lib/cimi/service/machine_image_create.rb
 create mode 100644 server/lib/cimi/service/machine_template.rb
 create mode 100644 server/lib/cimi/service/machine_template_create.rb
 create mode 100644 server/lib/cimi/service/machine_volume.rb
 create mode 100644 server/lib/cimi/service/network.rb
 create mode 100644 server/lib/cimi/service/network_configuration.rb
 create mode 100644 server/lib/cimi/service/network_create.rb
 create mode 100644 server/lib/cimi/service/network_port.rb
 create mode 100644 server/lib/cimi/service/network_port_configuration.rb
 create mode 100644 server/lib/cimi/service/network_port_template.rb
 create mode 100644 server/lib/cimi/service/network_template.rb
 create mode 100644 server/lib/cimi/service/resource_metadata.rb
 create mode 100644 server/lib/cimi/service/system.rb
 create mode 100644 server/lib/cimi/service/system_template.rb
 create mode 100644 server/lib/cimi/service/volume.rb
 create mode 100644 server/lib/cimi/service/volume_configuration.rb
 create mode 100644 server/lib/cimi/service/volume_create.rb
 create mode 100644 server/lib/cimi/service/volume_image.rb
 create mode 100644 server/lib/cimi/service/volume_image_create.rb
 create mode 100644 server/lib/cimi/service/volume_template.rb
 create mode 100644 server/lib/cimi/service/volume_template_create.rb

diff --git a/server/lib/cimi/models/action.rb b/server/lib/cimi/models/action.rb
index c1c9908..c83913e 100644
--- a/server/lib/cimi/models/action.rb
+++ b/server/lib/cimi/models/action.rb
@@ -17,8 +17,4 @@ class CIMI::Model::Action < CIMI::Model::Base
 
   text :action
 
-  def name
-    action.split('/').last.strip.intern
-  end
-
 end
diff --git a/server/lib/cimi/models/address.rb b/server/lib/cimi/models/address.rb
index 57e8be1..453e688 100644
--- a/server/lib/cimi/models/address.rb
+++ b/server/lib/cimi/models/address.rb
@@ -39,42 +39,4 @@ class CIMI::Model::Address < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id==:all
-      addresses = context.driver.addresses(context.credentials)
-      addresses.map{|addr| from_address(addr, context)}
-    else
-      address = context.driver.address(context.credentials, {:id=>id})
-      from_address(address, context)
-    end
-  end
-
-  def self.delete!(id, context)
-    context.driver.delete_address(context.credentials, id)
-    new(:id => id).destroy
-  end
-
-  private
-
-  def self.from_address(address, context)
-    self.new(
-      :name => address.id,
-      :id => context.address_url(address.id),
-      :description => "Address #{address.id}",
-      :ip => address.id,
-      :allocation => "dynamic",
-      :default_gateway => "unknown",
-      :dns => "unknown",
-      :protocol => protocol_from_address(address.id),
-      :mask => "unknown",
-      :resource => (address.instance_id) ? {:href=> context.machine_url(address.instance_id)} : nil,
-      :network => nil
-    )
-  end
-
-  def self.protocol_from_address(address)
-    addr = IPAddr.new(address)
-    addr.ipv4? ? "ipv4" : "ipv6"
-  end
-
 end
diff --git a/server/lib/cimi/models/address_create.rb b/server/lib/cimi/models/address_create.rb
index cf321ce..ffa08c4 100644
--- a/server/lib/cimi/models/address_create.rb
+++ b/server/lib/cimi/models/address_create.rb
@@ -17,35 +17,4 @@ class CIMI::Model::AddressCreate < CIMI::Model::Base
 
   ref :address_template, :required => true
 
-  def create(context)
-    validate!
-
-    if address_template.href?
-      template = address_template.find(context)
-    end
-
-    params = {
-      :name => name,
-      :description => description,
-      :address_template => template,
-      :env => context # FIXME: We should not pass the context to the driver (!)
-    }
-
-    unless context.driver.respond_to? :create_address
-       raise Deltacloud::Exceptions.exception_from_status(
-         501,
-         "Creating Address is not supported by the current driver"
-       )
-    end
-
-    address = context.driver.create_address(context.credentials, params)
-
-    result = CIMI::Model::Address.from_address(address, context)
-    result.name = name if name
-    result.description = description if description
-    result.property = property if property
-    result.save
-    result
-  end
-
 end
diff --git a/server/lib/cimi/models/address_template.rb b/server/lib/cimi/models/address_template.rb
index 9b5000b..bc66ccc 100644
--- a/server/lib/cimi/models/address_template.rb
+++ b/server/lib/cimi/models/address_template.rb
@@ -24,51 +24,4 @@ class CIMI::Model::AddressTemplate < CIMI::Model::Base
   array :operations do
     scalar :rel, :href
   end
-
-  def self.find(id, context)
-    if id==:all
-      if context.driver.respond_to? :address_templates
-        context.driver.address_templates(context.credentials, {:env=>context})
-      else
-        current_db.address_templates.map { |t| from_db(t, context) }
-      end
-    else
-      if context.driver.respond_to? :address_templates
-        context.driver.address_templates(context.credentials, {:id=>id, :env=>context})
-      else
-        template = current_db.address_templates_dataset.first(:id => id)
-        raise CIMI::Model::NotFound unless template
-        from_db(template, context)
-      end
-    end
-  end
-
-  def self.delete!(id, context)
-    current_db.address_templates.first(:id => id).destroy
-  end
-
-  private
-
-  def self.from_db(model, context)
-    self.new(
-      :id => context.address_template_url(model.id),
-      :name => model.name,
-      :description => model.description,
-      :ip => model.ip,
-      :hostname => model.hostname,
-      :allocation => model.allocation,
-      :default_gateway => model.default_gateway,
-      :dns => model.dns,
-      :protocol => model.protocol,
-      :mask => model.mask,
-      :property => (model.ent_properties ? JSON::parse(model.ent_properties) :  nil),
-      :operations => [
-        {
-          :href => context.destroy_address_template_url(model.id),
-          :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
-        }
-      ]
-    )
-  end
-
 end
diff --git a/server/lib/cimi/models/address_template_create.rb b/server/lib/cimi/models/address_template_create.rb
index e9ce3d3..601154d 100644
--- a/server/lib/cimi/models/address_template_create.rb
+++ b/server/lib/cimi/models/address_template_create.rb
@@ -25,20 +25,4 @@ class CIMI::Model::AddressTemplateCreate < CIMI::Model::Base
 
   href :network
 
-  def create(context)
-    validate!
-    new_template = context.current_db.add_address_template(
-      :name => name,
-      :description => description,
-      :hostname => hostname,
-      :ip => ip,
-      :allocation => allocation,
-      :default_gateway => default_gateway,
-      :dns => dns,
-      :protocol => protocol,
-      :mask => mask,
-      :ent_properties => property.to_json
-    )
-    CIMI::Model::AddressTemplate.from_db(new_template, context)
-  end
 end
diff --git a/server/lib/cimi/models/cloud_entry_point.rb b/server/lib/cimi/models/cloud_entry_point.rb
index 6c28e53..a016004 100644
--- a/server/lib/cimi/models/cloud_entry_point.rb
+++ b/server/lib/cimi/models/cloud_entry_point.rb
@@ -37,34 +37,6 @@ class CIMI::Model::CloudEntryPoint < CIMI::Model::Base
     href coll.underscore
   end
 
-  def self.create(context)
-    self.new(entities(context).merge({
-      :name => context.driver.name,
-      :description => "Cloud Entry Point for the Deltacloud #{context.driver.name} driver",
-      :driver => context.driver.name,
-      :provider => context.current_provider,
-      :id => context.cloudEntryPoint_url,
-      :base_uri => context.base_uri + "/",
-      :created => Time.now.xmlschema
-    }))
-  end
-
-  # Return an Hash of the CIMI root entities used in CloudEntryPoint
-  def self.entities(context)
-    CIMI::Collections.modules(:cimi).inject({}) do |supported_entities, m|
-      m.collections.each do |c|
-        index_operation_capability = c.operation(:index).required_capability
-        next if m.settings.respond_to?(:capability) and !m.settings.capability(index_operation_capability)
-        supported_entities[c.collection_name.to_s] = { :href => context.send(:"#{c.collection_name}_url") }
-      end
-      supported_entities
-    end
-  end
-
-  def entities
-    @attribute_values.clone.delete_if { |key, value| !value.respond_to? :href }
-  end
-
   private
 
   def self.href_defined?(resource)
diff --git a/server/lib/cimi/models/credential.rb b/server/lib/cimi/models/credential.rb
index 872248f..e16d64a 100644
--- a/server/lib/cimi/models/credential.rb
+++ b/server/lib/cimi/models/credential.rb
@@ -25,38 +25,4 @@ class CIMI::Model::Credential < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id == :all
-      return [] unless context.driver.respond_to?(:keys)
-      keys = context.driver.keys(context.credentials)
-      keys.map { |key| from_key(key, context) }
-    else
-      key = context.driver.key(context.credentials, :id => id)
-      from_key(key, context)
-    end
-  end
-
-  def self.create_from_xml(body, context)
-    credential = Credential.from_xml(body)
-    key = context.driver.create_key(context.credentials, :key_name => credential.name)
-    from_key(key, context)
-  end
-
-  def self.delete!(id, context)
-    context.driver.destroy_key(context.credentials, :id => id)
-  end
-
-  private
-
-  def self.from_key(key, context)
-    self.new(
-      :name => key.id,
-      :username => key.username,
-      :password => key.is_password? ? key.password : key.fingerprint,
-      :key => key.is_key? ? key.pem_rsa_key : nil,
-      :id => context.credential_url(key.id),
-      :created => Time.now.xmlschema
-    )
-  end
-
 end
diff --git a/server/lib/cimi/models/credential_create.rb b/server/lib/cimi/models/credential_create.rb
index 6479769..c02d68e 100644
--- a/server/lib/cimi/models/credential_create.rb
+++ b/server/lib/cimi/models/credential_create.rb
@@ -17,30 +17,4 @@ class CIMI::Model::CredentialCreate < CIMI::Model::Base
 
   ref :credential_template, :required => true
 
-  def create(context)
-    validate!
-
-    unless context.driver.respond_to? :create_key
-       raise Deltacloud::Exceptions.exception_from_status(
-         501,
-         "Creating Credential is not supported by the current driver"
-       )
-    end
-
-    if credential_template.href?
-      template = credential_template.find(ctx)
-    else
-      template = credential_template
-    end
-
-    key = context.driver.create_key(context.credentials, :key_name => name)
-
-    result = CIMI::Model::Credential.from_key(key, context)
-    result.name = name if name
-    result.description = description if description
-    result.property = property if property
-    result.save
-    result
-
-  end
 end
diff --git a/server/lib/cimi/models/credential_template.rb b/server/lib/cimi/models/credential_template.rb
index 1148c42..c263cef 100644
--- a/server/lib/cimi/models/credential_template.rb
+++ b/server/lib/cimi/models/credential_template.rb
@@ -19,6 +19,4 @@ class CIMI::Model::CredentialTemplate < CIMI::Model::Base
   text :password, :required => true
   text :key, :required => true
 
-  # TODO: tbd
-
 end
diff --git a/server/lib/cimi/models/disk.rb b/server/lib/cimi/models/disk.rb
index c725721..b358568 100644
--- a/server/lib/cimi/models/disk.rb
+++ b/server/lib/cimi/models/disk.rb
@@ -22,60 +22,4 @@ class CIMI::Model::Disk < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(instance, machine_config, context, id=:all)
-    if id == :all
-      name = instance.id+"_disk_" #assuming one disk for now...
-
-      if machine_config
-        mach_config_disks = machine_config.disks
-        return mach_config_disks.map do |d|
-          self.new(
-            :id => context.machine_url(instance.id) + "/disks/#{name}#{d[:capacity]}",
-            :name => "#{name}#{d[:capacity]}",
-            :description => "Disk for Machine #{instance.id}",
-            :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
-            :capacity => d[:capacity]
-          )
-        end
-      else
-        if instance.instance_profile.override? :storage
-          capacity = context.to_kibibyte(instance.instance_profile.storage, 'MB')
-        else
-          hw_profile = context.driver.hardware_profile(context.credentials, :id => instance.instance_profile.name)
-          if hw_profile.storage
-            capacity = context.to_kibibyte(hw_profile.storage.value, 'MB')
-          end
-        end
-
-        return [] unless capacity
-
-        [self.new(
-          :id => context.machine_url(instance.id)+"/disks/#{name}#{capacity}",
-          :name => name + capacity.to_s,
-          :description => "Disk for Machine #{instance.id}",
-          :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
-          :capacity => capacity
-        )]
-      end
-    else
-    end
-  end
-
-  def self.collection_for_instance(instance_id, context)
-    instance = context.driver.instance(context.credentials, :id => instance_id)
-    disks = find(instance, nil, context)
-    unless CIMI::Model.const_defined?('DiskCollection')
-      collection_class = CIMI::Model::Collection.generate(self)
-    else
-      collection_class = CIMI::Model::DiskCollection
-    end
-    collection_class.new(
-      :id => context.url("/machines/#{instance_id}/disks"),
-      :name => 'default',
-      :count => disks.size,
-      :description => "Disk collection for Machine #{instance_id}",
-      :entries => disks
-    )
-  end
-
 end
diff --git a/server/lib/cimi/models/forwarding_group.rb b/server/lib/cimi/models/forwarding_group.rb
index 221c0b2..ea55de5 100644
--- a/server/lib/cimi/models/forwarding_group.rb
+++ b/server/lib/cimi/models/forwarding_group.rb
@@ -25,12 +25,4 @@ class CIMI::Model::ForwardingGroup < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id==:all
-      context.driver.forwarding_groups(context.credentials, {:env=>context})
-    else
-      context.driver.forwarding_groups(context.credentials, {:env=>context, :id=>id})
-    end
-  end
-
 end
diff --git a/server/lib/cimi/models/forwarding_group_template.rb b/server/lib/cimi/models/forwarding_group_template.rb
index fca2f71..ae4c280 100644
--- a/server/lib/cimi/models/forwarding_group_template.rb
+++ b/server/lib/cimi/models/forwarding_group_template.rb
@@ -25,12 +25,4 @@ class CIMI::Model::ForwardingGroupTemplate < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id==:all
-      context.driver.forwarding_group_templates(context.credentials, {:env=>context})
-    else
-      context.driver.forwarding_group_templates(context.credentials, {:env=>context, :id=>id})
-    end
-  end
-
 end
diff --git a/server/lib/cimi/models/machine_configuration.rb b/server/lib/cimi/models/machine_configuration.rb
index 69c9eb5..5226582 100644
--- a/server/lib/cimi/models/machine_configuration.rb
+++ b/server/lib/cimi/models/machine_configuration.rb
@@ -30,35 +30,4 @@ class CIMI::Model::MachineConfiguration < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    profiles = []
-    if id == :all
-      profiles = context.driver.hardware_profiles(context.credentials)
-      profiles.map { |profile| from_hardware_profile(profile, context) }.compact
-    else
-      profile = context.driver.hardware_profile(context.credentials, id)
-      from_hardware_profile(profile, context)
-    end
-  end
-
-  private
-  def self.from_hardware_profile(profile, context)
-    # We accept just profiles with all properties set
-    return unless profile.memory or profile.cpu or profile.storage
-    memory = profile.memory ? context.to_kibibyte((profile.memory.value || profile.memory.default), profile.memory.unit) : nil
-    cpu = (profile.cpu ? (profile.cpu.value || profile.cpu.default) : nil )
-    storage = profile.storage ? context.to_kibibyte((profile.storage.value || profile.storage.default), profile.storage.unit) :  nil
-    machine_hash = {
-      :name => profile.name,
-      :description => "Machine Configuration with #{memory} KiB "+
-        "of memory and #{cpu} CPU",
-      :cpu => ( cpu.to_i.to_s if cpu ) ,
-      :created => Time.now.xmlschema,  # FIXME: DC hardware_profile has no mention about created_at
-      :memory => (memory if memory),
-      :disks => (  [ { :capacity => storage, :format => (profile.storage.respond_to?(:format) ? profile.storage.format : "unknown")  } ] if storage ), #no format attr for hwp - may be added if providers support...,
-      :id => context.machine_configuration_url(profile.id)
-    }
-    self.new(machine_hash)
-  end
-
 end
diff --git a/server/lib/cimi/models/machine_create.rb b/server/lib/cimi/models/machine_create.rb
index 0f04c01..3b3e0d9 100644
--- a/server/lib/cimi/models/machine_create.rb
+++ b/server/lib/cimi/models/machine_create.rb
@@ -14,36 +14,8 @@
 # under the License.
 
 class CIMI::Model::MachineCreate < CIMI::Model::Base
+
   ref :machine_template
   text :realm
 
-  def create(ctx)
-    params = {}
-    if machine_template.href
-      template = machine_template.find(ctx)
-      params[:hwp_id] = template.machine_config.ref_id(ctx)
-      params[:initial_state] = template.initial_state
-      image_id = template.machine_image.ref_id(ctx)
-    else
-      # FIXME: What if either of these href's isn't there ? What if the user
-      # tries to override some aspect of the machine_config/machine_image ?
-      params[:hwp_id] = machine_template.machine_config.href.split('/').last
-      params[:initial_state] = machine_template.initial_state
-      image_id = machine_template.machine_image.href.split('/').last
-      if machine_template.credential.href
-        params[:keyname] = machine_template.credential.href.split('/').last
-      end
-    end
-
-    params[:name] = name if name
-    params[:realm_id] = realm if realm
-    instance = ctx.driver.create_instance(ctx.credentials, image_id, params)
-
-    result = CIMI::Model::Machine::from_instance(instance, ctx)
-    result.name = name if name
-    result.description = description if description
-    result.property = property if property
-    result.save
-    result
-  end
 end
diff --git a/server/lib/cimi/models/machine_image_create.rb b/server/lib/cimi/models/machine_image_create.rb
index 365d640..890241d 100644
--- a/server/lib/cimi/models/machine_image_create.rb
+++ b/server/lib/cimi/models/machine_image_create.rb
@@ -19,23 +19,4 @@ class CIMI::Model::MachineImageCreate < CIMI::Model::Base
   text :image_location, :required => true
   href :related_image
 
-  def create(context)
-    validate!
-
-    params = {
-      :id => context.href_id(image_location, :machines),
-      :name => name,
-      :description => description
-    }
-
-    img = context.driver.create_image(context.credentials, params)
-
-    result = CIMI::Model::MachineImage.from_image(img, context)
-    result.name = name if name
-    result.description = description if description
-    result.property = property if property
-    result.save
-    result
-  end
-
 end
diff --git a/server/lib/cimi/models/machine_template.rb b/server/lib/cimi/models/machine_template.rb
index eed8fa9..812ad15 100644
--- a/server/lib/cimi/models/machine_template.rb
+++ b/server/lib/cimi/models/machine_template.rb
@@ -43,39 +43,4 @@ class CIMI::Model::MachineTemplate < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  class << self
-    def find(id, context)
-      if id == :all
-        current_db.machine_templates.map { |t| from_db(t, context) }
-      else
-        template = current_db.machine_templates_dataset.first(:id => id)
-        raise CIMI::Model::NotFound unless template
-        from_db(template, context)
-      end
-    end
-
-    def delete!(id, context)
-      current_db.machine_templates.first(:id => id).destroy
-    end
-
-    def from_db(model, context)
-      self.new(
-        :id => context.machine_template_url(model.id),
-        :name => model.name,
-        :description => model.description,
-        :machine_config => { :href => model.machine_config },
-        :machine_image => { :href => model.machine_image },
-        :realm => model.realm,
-        :property => (model.ent_properties ? JSON::parse(model.ent_properties) :  nil),
-        :created => Time.parse(model.created_at.to_s).xmlschema,
-        :operations => [
-          {
-            :href => context.destroy_machine_template_url(model.id),
-            :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
-          }
-        ]
-      )
-    end
-  end
-
 end
diff --git a/server/lib/cimi/models/machine_template_create.rb b/server/lib/cimi/models/machine_template_create.rb
index 5e5e411..4d46b79 100644
--- a/server/lib/cimi/models/machine_template_create.rb
+++ b/server/lib/cimi/models/machine_template_create.rb
@@ -18,16 +18,4 @@ class CIMI::Model::MachineTemplateCreate < CIMI::Model::Base
   href :machine_config, :required => true
   href :machine_image, :required => true
 
-  def create(context)
-    validate!
-    new_template = self.class.current_db.add_machine_template(
-      :name => name,
-      :description => description,
-      :machine_config => machine_config.href,
-      :machine_image => machine_image.href,
-      :ent_properties => property.to_json
-    )
-    CIMI::Model::MachineTemplate.from_db(new_template, context)
-  end
-
 end
diff --git a/server/lib/cimi/models/machine_volume.rb b/server/lib/cimi/models/machine_volume.rb
index 7631138..50b8b76 100644
--- a/server/lib/cimi/models/machine_volume.rb
+++ b/server/lib/cimi/models/machine_volume.rb
@@ -22,69 +22,4 @@ class CIMI::Model::MachineVolume < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(instance_id, context, id=:all)
-    if id == :all
-      volumes = context.driver.storage_volumes(context.credentials)
-      volumes.inject([]) do |attached, vol|
-        id = context.machine_url(instance_id)+"/volumes/#{vol.id}"
-        attached <<  self.new(
-          :id => id,
-          :name => vol.id,
-          :description => "MachineVolume #{vol.id} for Machine #{instance_id}",
-          :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
-          :initial_location => vol.device,
-          :volume => {:href=>context.volume_url(vol.id)},
-          :operations => [{:href=>id, :rel => "delete" }]
-          ) if vol.instance_id == instance_id
-        attached
-      end
-    else
-      vol = context.driver.storage_volume(context.credentials, {:id=>id})
-      id = context.machine_url(instance_id)+"/volumes/#{vol.id}"
-      raise CIMI::Model::NotFound unless vol.instance_id == instance_id
-      self.new(
-        :id => id,
-        :name => vol.id,
-        :description => "MachineVolume #{vol.id} for Machine #{instance_id}",
-        :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
-        :initial_location => vol.device,
-        :volume => {:href=>context.volume_url(vol.id)},
-        :operations => [{:href=>id, :rel => "delete" }]
-        )
-    end
-  end
-
-  def self.find_to_attach_from_xml(xml_in, context)
-    xml = XmlSimple.xml_in(xml_in)
-    vol_id = xml["volume"].first["href"].split("/").last
-    location = xml["initialLocation"].first.strip
-    [vol_id, location]
-  end
-
-  def self.find_to_attach_from_json(json_in, context)
-    json = JSON.parse(json_in)
-    vol_id = json["volume"]["href"].split("/").last
-    location = json["initialLocation"]
-    [vol_id, location]
-  end
-
-
-  def self.collection_for_instance(instance_id, context)
-    machine_volumes = self.find(instance_id, context)
-    volumes_url = context.url("/machines/#{instance_id}/volumes")
-    unless CIMI::Model.const_defined?('MachineVolumeCollection')
-      collection_class = CIMI::Model::Collection.generate(self)
-    else
-      collection_class = CIMI::Model::MachineVolumeCollection
-    end
-    collection_class.new(
-      :id => volumes_url,
-      :name => 'default',
-      :count => machine_volumes.size,
-      :description => "Volume collection for Machine #{instance_id}",
-      :entries => machine_volumes,
-      :operations => [{ :href => volumes_url.singularize+"_attach", :rel => "add" }]
-    )
-  end
-
 end
diff --git a/server/lib/cimi/models/network.rb b/server/lib/cimi/models/network.rb
index 789e83f..1b8587a 100644
--- a/server/lib/cimi/models/network.rb
+++ b/server/lib/cimi/models/network.rb
@@ -37,36 +37,4 @@ class CIMI::Model::Network < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    networks=[]
-    if id==:all
-      networks = context.driver.networks(context.credentials, {:env=>context})
-    else
-      networks = context.driver.networks(context.credentials, {:id=>id, :env=>context})
-    end
-    if context.expand? :networkPorts
-      networks.each do |network|
-        network.network_ports = CIMI::Model::NetworkPort.collection_for_network(network.id, context)
-      end
-    end
-    networks
-  end
-
-
-  def self.delete!(id, context)
-    context.driver.delete_network(context.credentials, id)
-  end
-
-  def perform(action, context, &block)
-    begin
-      if context.driver.send(:"#{action.name}_network", context.credentials, self.name)
-        block.callback :success
-      else
-        raise "Operation #{action.name} failed to execute on the Network #{self.name} "
-      end
-    rescue => e
-      block.callback :failure, e.message
-    end
-  end
-
 end
diff --git a/server/lib/cimi/models/network_configuration.rb b/server/lib/cimi/models/network_configuration.rb
index 1010d54..c7d37ba 100644
--- a/server/lib/cimi/models/network_configuration.rb
+++ b/server/lib/cimi/models/network_configuration.rb
@@ -27,19 +27,4 @@ class CIMI::Model::NetworkConfiguration < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    network_configs = []
-    if id==:all
-      network_configs = context.driver.network_configurations(context.credentials, {:env=>context})
-    else
-      network_configs = context.driver.network_configurations(context.credentials, {:env=>context, :id=>id})
-    end
-    network_configs
-  end
-
-  def self.create_from_xml(request_body, context)
-  end
-
-  def self.create_from_json(request_body, context)
-  end
 end
diff --git a/server/lib/cimi/models/network_create.rb b/server/lib/cimi/models/network_create.rb
index 2496269..ea3e170 100644
--- a/server/lib/cimi/models/network_create.rb
+++ b/server/lib/cimi/models/network_create.rb
@@ -17,27 +17,4 @@ class CIMI::Model::NetworkCreate < CIMI::Model::Base
 
   ref :network_template, :required => true
 
-  def create(context)
-    validate!
-    if network_template.href?
-      template = network_template.find(context)
-      network_config = template.network_config.find(context)
-      forwarding_group = template.forwarding_group.find(context)
-    else
-      network_config = CIMI::Model::NetworkConfiguration.find(context.href_id(network_template.network_config.href, :network_configurations), context)
-      forwarding_group = CIMI::Model::ForwardingGroup.find(context.href_id(network_template.forwarding_group.href, :forwarding_groups), context)
-    end
-    params = {
-      :network_config => network_config,
-      :forwarding_group => forwarding_group,
-      :name => name,
-      :description => description,
-      :env => context # FIXME: We should not pass the context to the driver (!)
-    }
-    network = context.driver.create_network(context.credentials, params)
-    network.property = property if property
-    network.save
-    network
-  end
-
 end
diff --git a/server/lib/cimi/models/network_port.rb b/server/lib/cimi/models/network_port.rb
index 03b0ca3..3f6b371 100644
--- a/server/lib/cimi/models/network_port.rb
+++ b/server/lib/cimi/models/network_port.rb
@@ -33,77 +33,4 @@ class CIMI::Model::NetworkPort < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id==:all
-      context.driver.network_ports(context.credentials, {:env=>context})
-    else
-      context.driver.network_ports(context.credentials, {:id=>id, :env=>context})
-    end
-  end
-
-  def self.create(request_body, context, type)
-    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false, "NormaliseSpace"=>2}) : JSON.parse(request_body)
-    if input["networkPortTemplate"]["href"] #template by reference
-      network_port_config, network = get_by_reference(input, context)
-    else
-      if input["networkPortTemplate"]["networkPortConfig"]["href"] # configuration by reference
-        network_port_config = CIMI::Model::NetworkPortConfiguration.find(context.href_id(input["networkPortTemplate"]["networkPortConfig"]["href"],:network_port_configurations), context)
-      else #configuration by value
-        network_port_config = get_by_value(request_body, type)
-      end
-      network = CIMI::Model::Network.find(context.href_id(input["networkPortTemplate"]["network"]["href"], :networks), context)
-    end
-    params = {:network_port_config => network_port_config, :network => network, :name=>input["name"], :description=>input["description"], :env=>context}
-    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
-    context.driver.create_network_port(context.credentials, params)
-  end
-
-  def self.delete!(id, context)
-    context.driver.delete_network_port(context.credentials, id)
-  end
-
-  def perform(action, context, &block)
-    begin
-      if context.driver.send(:"#{action.name}_network_port", context.credentials, self.name)
-        block.callback :success
-      else
-        raise "Operation #{action.name} failed to execute on the NetworkPort #{self.name} "
-      end
-    rescue => e
-      block.callback :failure, e.message
-    end
-  end
-
-  def self.collection_for_network(network_id, context)
-    net_url = context.network_url(network_id)
-    network_ports = CIMI::Model::NetworkPort.all(context)
-    ports_collection = network_ports.inject([]){|res, current| res << current if current.network.href == net_url ; res}
-    CIMI::Model::NetworkPortCollection.new(
-      :id => net_url+"/network_ports",
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} NetworkPortCollection",
-      :count => ports_collection.size,
-      :network_ports => ports_collection
-    )
-  end
-
-  private
-
-  def self.get_by_reference(input, context)
-    network_port_template = CIMI::Model::NetworkPortTemplate.find(context.href_id(input["networkPortTemplate"]["href"], :network_port_templates), context)
-    network_port_config = CIMI::Model::NetworkPortConfiguration.find(context.href_id(network_port_template.network_port_config.href, :network_port_configurations), context)
-    network = CIMI::Model::Network.find(context.href_id(network_port_template.network.href, :networks), context)
-    return network_port_config, network
-  end
-
-  def self.get_by_value(request_body, type)
-    if type == :xml
-      xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
-      network_port_config = CIMI::Model::NetworkPortConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["networkPortTemplate"][0]["networkPortConfig"][0]))
-    else
-     json = JSON.parse(request_body)
-      network_port_config = CIMI::Model::NetworkPortConfiguration.from_json(JSON.generate(json["networkPortTemplate"]["networkPortConfig"]))
-    end
-  end
 end
diff --git a/server/lib/cimi/models/network_port_configuration.rb b/server/lib/cimi/models/network_port_configuration.rb
index 3789b35..8f505b5 100644
--- a/server/lib/cimi/models/network_port_configuration.rb
+++ b/server/lib/cimi/models/network_port_configuration.rb
@@ -25,12 +25,4 @@ class CIMI::Model::NetworkPortConfiguration < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id==:all
-      context.driver.network_port_configurations(context.credentials, {:env=>context})
-    else
-      context.driver.network_port_configurations(context.credentials, {:env=>context, :id=>id})
-    end
-  end
-
 end
diff --git a/server/lib/cimi/models/network_port_template.rb b/server/lib/cimi/models/network_port_template.rb
index 774d6e9..8e7c738 100644
--- a/server/lib/cimi/models/network_port_template.rb
+++ b/server/lib/cimi/models/network_port_template.rb
@@ -25,12 +25,4 @@ class CIMI::Model::NetworkPortTemplate < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id==:all
-      context.driver.network_port_templates(context.credentials, {:env=>context})
-    else
-      context.driver.network_port_templates(context.credentials, {:env=>context, :id=>id})
-    end
-  end
-
 end
diff --git a/server/lib/cimi/models/network_template.rb b/server/lib/cimi/models/network_template.rb
index a16c094..4f69f52 100644
--- a/server/lib/cimi/models/network_template.rb
+++ b/server/lib/cimi/models/network_template.rb
@@ -24,14 +24,4 @@ class CIMI::Model::NetworkTemplate < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    network_templates = []
-    if id==:all
-      network_templates = context.driver.network_templates(context.credentials, {:env=>context})
-    else
-      network_templates = context.driver.network_templates(context.credentials, {:env=>context, :id=>id})
-    end
-    network_templates
-  end
-
 end
diff --git a/server/lib/cimi/models/resource_metadata.rb b/server/lib/cimi/models/resource_metadata.rb
index 3ed88db..2c4ee08 100644
--- a/server/lib/cimi/models/resource_metadata.rb
+++ b/server/lib/cimi/models/resource_metadata.rb
@@ -16,6 +16,7 @@
 
 class CIMI::Model::ResourceMetadata < CIMI::Model::Base
 
+  # FIXME: Is this property really needed? (Base model include 'name'
   text :name
 
   text :type_uri
@@ -51,98 +52,13 @@ class CIMI::Model::ResourceMetadata < CIMI::Model::Base
     scalar :rel, :href
   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
-    else
-      resource_class = CIMI::Model.const_get("#{id.camelize}")
-      resource_metadata_for(resource_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
-    self.new({ :id => context.resource_metadata_url(cimi_resource.underscore),
-              :name => cimi_resource,
-              :type_uri => resource_class.resource_uri,
-              :attributes => attributes,
-              :capabilities => capabilities,
-              :actions => actions
-    })
-  end
-
-  def self.resource_attributes
-    @resource_attributes ||= {}
-  end
-
   def self.add_resource_attribute!(klass, name, opts={})
     resource_attributes[klass.name] ||= {}
     resource_attributes[klass.name][name] = opts
   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
-
-  def self.rm_capabilities_for(resource_class,context)
-    cimi_object = resource_class.name.split("::").last.underscore.pluralize.to_sym
-    capabilities = (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
-#cimi_resource.underscore.pluralize.to_sym
-  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 self.resource_attributes
+    @resource_attributes ||= {}
   end
 
 end
diff --git a/server/lib/cimi/models/system.rb b/server/lib/cimi/models/system.rb
index e238259..118f9f5 100644
--- a/server/lib/cimi/models/system.rb
+++ b/server/lib/cimi/models/system.rb
@@ -19,49 +19,25 @@ class CIMI::Model::System < CIMI::Model::Base
 
   text :state
 
-#  collection :systems, :class => CIMI::Model::SystemSystem
-#  collection :machines, :class => CIMI::Model::SystemMachine
-#  collection :credentials, :class => CIMI::Model::SystemCredential
-#  collection :volumes, :class => CIMI::Model::SystemVolume
-#  collection :networks, :class => CIMI::Model::SystemNetwork
-#  collection :network_ports, :class => CIMI::Model::SystemNetworkPort
-#  collection :addresses, :class => CIMI::Model::SystemAddress
-#  collection :forwarding_groups, :class => CIMI::Model::SystemForwardingGroup
+  # FIXME: Any reason for these comments?
 
-#  array :meters do
-#    scalar :href
-#  end
+  #  collection :systems, :class => CIMI::Model::SystemSystem
+  #  collection :machines, :class => CIMI::Model::SystemMachine
+  #  collection :credentials, :class => CIMI::Model::SystemCredential
+  #  collection :volumes, :class => CIMI::Model::SystemVolume
+  #  collection :networks, :class => CIMI::Model::SystemNetwork
+  #  collection :network_ports, :class => CIMI::Model::SystemNetworkPort
+  #  collection :addresses, :class => CIMI::Model::SystemAddress
+  #  collection :forwarding_groups, :class => CIMI::Model::SystemForwardingGroup
 
-#  href :event_log
+  #  array :meters do
+  #    scalar :href
+  #  end
+
+  #  href :event_log
 
   array :operations do
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id == :all
-      systems = context.driver.systems(context.credentials, {:env=>context})
-    else
-      systems = context.driver.systems(context.credentials, {:env=>context, :id=>id})
-      raise CIMI::Model::NotFound unless systems.first
-      systems.first
-    end
-  end
-
-  def perform(action, context, &block)
-    begin
-      if context.driver.send(:"#{action.name}_system", context.credentials, self.id.split("/").last)
-        block.callback :success
-      else
-        raise "Operation failed to execute on given System"
-      end
-    rescue => e
-      block.callback :failure, e.message
-    end
-  end
-
-  def self.delete!(id, context)
-    context.driver.destroy_system(context.credentials, id)
-  end
-
 end
diff --git a/server/lib/cimi/models/system_template.rb b/server/lib/cimi/models/system_template.rb
index 6a6e1f2..82e418b 100644
--- a/server/lib/cimi/models/system_template.rb
+++ b/server/lib/cimi/models/system_template.rb
@@ -21,43 +21,29 @@ class CIMI::Model::SystemTemplate < CIMI::Model::Base
     text :name, :description
     hash_map :properties
     text :type
+
+    # FIXME: Any reasons for these comments?
+
     #component_template, comprises:
-#    struct :machine_template, :class => CIMI::Model::MachineTemplate
-#    struct :system_template, :class => CIMI::Model::SystemTemplate
-#    struct :credential_template, :class => CIMI::Model::CredentialTemplate
-#    struct :volume_template, :class => CIMI::Model::VolumeTemplate
-#    struct :network_template, :class => CIMI::Model::NetworkTemplate
-#    struct :network_port_template, :class => CIMI::Model::NetworkPortTemplate
-#    struct :forwarding_group_template, :class => CIMI::Model::ForwardingGroupTemplate
-#    struct :address_template, :class => CIMI::Model::AddressTemplate
+    #    struct :machine_template, :class => CIMI::Model::MachineTemplate
+    #    struct :system_template, :class => CIMI::Model::SystemTemplate
+    #    struct :credential_template, :class => CIMI::Model::CredentialTemplate
+    #    struct :volume_template, :class => CIMI::Model::VolumeTemplate
+    #    struct :network_template, :class => CIMI::Model::NetworkTemplate
+    #    struct :network_port_template, :class => CIMI::Model::NetworkPortTemplate
+    #    struct :forwarding_group_template, :class => CIMI::Model::ForwardingGroupTemplate
+    #    struct :address_template, :class => CIMI::Model::AddressTemplate
     text :quantity
   end
 
-#  array :meter_templates do
-#    scalar :href
-#  end
+  #  array :meter_templates do
+  #    scalar :href
+  #  end
 
-#  href :event_log_template
+  #  href :event_log_template
 
   array :operations do
     scalar :rel, :href
   end
 
-  class << self
-    def find(id, context)
-      if id == :all
-        templates = context.driver.system_templates(context.credentials, {:env=>context})
-      else
-        templates = context.driver.system_templates(context.credentials, {:env=>context, :id=>id})
-        raise CIMI::Model::NotFound unless templates.first
-        templates.first
-      end
-    end
-
-    def delete!(id, context)
-      context.driver.destroy_system_template(context.credentials, id)
-    end
-
-  end
-
 end
diff --git a/server/lib/cimi/models/volume.rb b/server/lib/cimi/models/volume.rb
index 888589a..a1b4423 100644
--- a/server/lib/cimi/models/volume.rb
+++ b/server/lib/cimi/models/volume.rb
@@ -37,63 +37,4 @@ class CIMI::Model::Volume < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    creds = context.credentials
-    if id == :all
-      volumes = context.driver.storage_volumes(creds)
-      volumes.collect{ |volume| from_storage_volume(volume, context) }
-    else
-      volume = context.driver.storage_volumes(creds, :id => id).first
-      raise CIMI::Model::NotFound unless volume
-      from_storage_volume(volume, context)
-    end
-  end
-
-  def self.all(context); find(:all, context); end
-
-  def self.delete!(id, context)
-    context.driver.destroy_storage_volume(context.credentials, {:id=>id} )
-    new(:id => id).destroy
-  end
-
-  def self.find_to_attach_from_json(json_in, context)
-    json = JSON.parse(json_in)
-    json["volumes"].map{|v| {:volume=>self.find(v["volume"]["href"].split("/volumes/").last, context),
-                             :initial_location=>v["initialLocation"]  }}
-  end
-
-  def self.find_to_attach_from_xml(xml_in, context)
-    xml = XmlSimple.xml_in(xml_in)
-    xml["volume"].map{|v| {:volume => self.find(v["href"].split("/volumes/").last, context),
-                           :initial_location=>v["initialLocation"] }}
-  end
-
-  def self.from_storage_volume(volume, context)
-    self.new( { :name => volume.id,
-                :created => volume.created.nil? ? nil : Time.parse(volume.created).xmlschema,
-                :id => context.volume_url(volume.id),
-                :capacity => context.to_kibibyte(volume.capacity, 'GB'),
-                :bootable => "false", #fixme ... will vary... ec2 doesn't expose this
-                :snapshots => [], #fixme...
-                :type => 'http://schemas.dmtf.org/cimi/1/mapped',
-                :state => volume.state == 'IN-USE' ? 'AVAILABLE' : volume.state,
-                :meters => [],
-                :operations => [{:href=> context.volume_url(volume.id), :rel => "delete"}]
-            } )
-  end
-
-  def self.collection_for_instance(instance_id, context)
-    instance = context.driver.instance(context.credentials, :id => instance_id)
-    volumes = instance.storage_volumes.map do |mappings|
-      mappings.keys.map { |volume_id| from_storage_volume(context.driver.storage_volume(context.credentials, :id => volume_id), context) }
-    end.flatten
-    CIMI::Model::VolumeCollection.new(
-      :id => context.url("/machines/#{instance_id}/volumes"),
-      :name => 'default',
-      :count => volumes.size,
-      :description => "Volume collection for Machine #{instance_id}",
-      :entries => volumes
-    )
-  end
-
 end
diff --git a/server/lib/cimi/models/volume_configuration.rb b/server/lib/cimi/models/volume_configuration.rb
index bf94a3a..7393b53 100644
--- a/server/lib/cimi/models/volume_configuration.rb
+++ b/server/lib/cimi/models/volume_configuration.rb
@@ -25,67 +25,4 @@ class CIMI::Model::VolumeConfiguration < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.create_from_json(body, context)
-    json = JSON.parse(body)
-    new_config = current_db.add_volume_configuration(
-      :name => json['name'],
-      :description => json['description'],
-      :format => json['format'],
-      :capacity => json['capacity'],
-      :ent_properties => (json['properties'] || {}).to_json
-    )
-    from_db(new_config, context)
-  end
-
-  def self.create_from_xml(body, context)
-    xml = XmlSimple.xml_in(body)
-    xml['property'] ||= []
-    new_config = current_db.add_volume_configuration(
-      :name => xml['name'].first,
-      :description => xml['description'].first,
-      :format => xml['format'].first,
-      :capacity => xml['capacity'].first,
-      :ent_properties =>  JSON::dump((xml['property'] || {}).inject({}){ |r, p| r[p['key']]=p['content']; r })
-    )
-    from_db(new_config, context)
-  end
-
-  def self.delete!(id, context)
-    current_db.volume_configurations.first(:id => id).destroy
-  end
-
-  def self.find(id, context)
-    if id==:all
-      if context.driver.respond_to? :volume_configurations
-        context.driver.volume_configurations(context.credentials, {:env=>context})
-      else
-        current_db.volume_configurations.map { |t| from_db(t, context) }
-      end
-    else
-      if context.driver.respond_to? :volume_configuration
-        context.driver.volume_configuration(context.credentials, id, :env=>context)
-      else
-        config = current_db.volume_configurations_dataset.first(:id => id)
-        raise CIMI::Model::NotFound unless config
-        from_db(config, context)
-      end
-    end
-  end
-
-  private
-
-  def self.from_db(model, context)
-    self.new(
-      :id => context.volume_configuration_url(model.id),
-      :name => model.name,
-      :description => model.description,
-      :format => model.format,
-      :capacity => context.to_kibibyte(model.capacity, "GB"),
-      :property => (model.ent_properties ? JSON::parse(model.ent_properties) :  nil),
-      :operations => [
-        { :href => context.destroy_volume_configuration_url(model.id), :rel => 'http://schemas.dmtf.org/cimi/1/action/delete' }
-      ]
-    )
-  end
-
 end
diff --git a/server/lib/cimi/models/volume_create.rb b/server/lib/cimi/models/volume_create.rb
index 607c407..1408c77 100644
--- a/server/lib/cimi/models/volume_create.rb
+++ b/server/lib/cimi/models/volume_create.rb
@@ -17,42 +17,4 @@ class CIMI::Model::VolumeCreate < CIMI::Model::Base
 
   ref :volume_template, :required => true
 
-  def create(context)
-    validate!
-
-    if volume_template.href?
-      template = volume_template.find(context)
-    else
-      template = CIMI::Model::VolumeTemplate.from_xml(volume_template.to_xml)
-    end
-
-    volume_image = template.volume_image.href? ?
-      template.volume_image.find(context) : template.volume_image
-
-    volume_config = template.volume_config.href? ?
-      template.volume_config.find(context) : template.volume_config
-
-    params = {
-      :name => name,
-      :capacity => volume_config.capacity,
-      :snapshot_id => ref_id(volume_image.id),
-    }
-
-    unless context.driver.respond_to? :create_storage_volume
-       raise Deltacloud::Exceptions.exception_from_status(
-         501,
-         "Creating Volume is not supported by the current driver"
-       )
-    end
-
-    volume = context.driver.create_storage_volume(context.credentials, params)
-
-    result = CIMI::Model::Volume.from_storage_volume(volume, context)
-    result.name = name if result.name.nil?
-    result.description = description if description
-    result.property = property if property
-    result.save
-    result
-  end
-
 end
diff --git a/server/lib/cimi/models/volume_image.rb b/server/lib/cimi/models/volume_image.rb
index ef06552..ec94289 100644
--- a/server/lib/cimi/models/volume_image.rb
+++ b/server/lib/cimi/models/volume_image.rb
@@ -24,34 +24,4 @@ class CIMI::Model::VolumeImage < CIMI::Model::Base
   array :operations do
     scalar :rel, :href
   end
-
-  def self.find(id, context)
-    creds = context.credentials
-    if id == :all
-      snapshots = context.driver.storage_snapshots(creds)
-      snapshots.collect{ |snapshot| from_storage_snapshot(snapshot, context) }
-    else
-      snapshot = context.driver.storage_snapshots(creds, id => :id).first
-      raise CIMI::Model::NotFound unless snapshot
-      from_storage_snapshot(snapshot, context)
-    end
-  end
-
-  def self.all(context); find(:all, context); end
-
-  def self.delete!(vol_image_id, context)
-    context.driver.destroy_storage_snapshot(context.credentials, {:id=>vol_image_id})
-  end
-
-  def self.from_storage_snapshot(snapshot, context)
-    self.new( {
-      :name => snapshot.name,
-      :description => snapshot.description,
-      :created => snapshot.created.nil? ? nil : Time.parse(snapshot.created).xmlschema,
-      :id => context.volume_image_url(snapshot.id),
-      :image_location => {:href=>context.volume_url(snapshot.storage_volume_id)},
-      :bootable => "false"  #FIXME
-    } )
-  end
-
 end
diff --git a/server/lib/cimi/models/volume_image_create.rb b/server/lib/cimi/models/volume_image_create.rb
index f953146..4eb0ed1 100644
--- a/server/lib/cimi/models/volume_image_create.rb
+++ b/server/lib/cimi/models/volume_image_create.rb
@@ -19,29 +19,4 @@ class CIMI::Model::VolumeImageCreate < CIMI::Model::Base
   text :image_data
   text :bootable, :required => true
 
-  def create(context)
-    validate!
-
-    params = {
-      :volume_id => context.href_id(image_location.href, :volumes),
-      :name => name,
-      :description => description
-    }
-
-    unless context.driver.respond_to? :create_storage_snapshot
-      raise Deltacloud::Exceptions.exception_from_status(
-        501,
-        'Creating VolumeImage is not supported by the current driver'
-      )
-    end
-
-    new_snapshot = context.driver.create_storage_snapshot(context.credentials, params)
-    result = CIMI::Model::VolumeImage.from_storage_snapshot(new_snapshot, context)
-    result.name= name unless new_snapshot.name
-    result.description = description unless new_snapshot.description
-    result.property = property if property
-    result.save
-    result
-  end
-
 end
diff --git a/server/lib/cimi/models/volume_template.rb b/server/lib/cimi/models/volume_template.rb
index 15cbcd0..bda4657 100644
--- a/server/lib/cimi/models/volume_template.rb
+++ b/server/lib/cimi/models/volume_template.rb
@@ -29,45 +29,4 @@ class CIMI::Model::VolumeTemplate < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    if id==:all
-      if context.driver.respond_to? :volume_templates
-        context.driver.volume_templates(context.credentials, {:env=>context})
-      else
-        current_db.volume_templates.map { |t| from_db(t, context) }
-      end
-    else
-      if context.driver.respond_to? :volume_template
-        context.driver.volume_template(context.credentials, id, :env=>context)
-      else
-        template = current_db.volume_templates_dataset.first(:id => id)
-        raise CIMI::Model::NotFound unless template
-        from_db(template, context)
-      end
-    end
-  end
-
-  def self.delete!(id, context)
-    current_db.volume_templates.first(:id => id).destroy
-  end
-
-  def self.from_db(model, context)
-    self.new(
-      :id => context.volume_template_url(model.id),
-      :name => model.name,
-      :description => model.description,
-      :volume_config => {:href => model.volume_config},
-      :volume_image => {:href => model.volume_image},
-      :property => (model.ent_properties ? JSON::parse(model.ent_properties) :  nil),
-      :operations => [
-        {
-          :href => context.destroy_volume_template_url(model.id),
-          :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
-        }
-      ]
-    )
-  end
-
-
-
 end
diff --git a/server/lib/cimi/models/volume_template_create.rb b/server/lib/cimi/models/volume_template_create.rb
index b6dbec2..3064ae8 100644
--- a/server/lib/cimi/models/volume_template_create.rb
+++ b/server/lib/cimi/models/volume_template_create.rb
@@ -18,16 +18,4 @@ class CIMI::Model::VolumeTemplateCreate < CIMI::Model::Base
   ref :volume_config, :required => true
   ref :volume_image, :required => true
 
-  def create(context)
-    validate!
-    new_template = self.class.current_db.add_volume_template(
-      :name => name,
-      :description => description,
-      :volume_config => volume_config.href,
-      :volume_image => volume_image.href,
-      :ent_properties => property.to_json
-    )
-    CIMI::Model::VolumeTemplate.from_db(new_template, context)
-  end
-
 end
diff --git a/server/lib/cimi/service.rb b/server/lib/cimi/service.rb
index f6b933f..b05efbf 100644
--- a/server/lib/cimi/service.rb
+++ b/server/lib/cimi/service.rb
@@ -27,3 +27,38 @@ require_relative './../db/volume_template'
 require_relative './service/base'
 require_relative './service/machine'
 require_relative './service/machine_image'
+require_relative './service/volume_image'
+require_relative './service/system_template'
+require_relative './service/network_port_configuration'
+require_relative './service/credential_create'
+require_relative './service/machine_template_create'
+require_relative './service/volume_create'
+require_relative './service/network_create'
+require_relative './service/network'
+require_relative './service/forwarding_group'
+require_relative './service/volume_template_create'
+require_relative './service/system'
+require_relative './service/address_template_create'
+require_relative './service/volume'
+require_relative './service/volume_image_create'
+require_relative './service/machine_configuration'
+require_relative './service/volume_template'
+require_relative './service/machine_template'
+require_relative './service/network_port'
+require_relative './service/forwarding_group_template'
+require_relative './service/credential_template'
+require_relative './service/volume_configuration'
+require_relative './service/cloud_entry_point'
+require_relative './service/network_configuration'
+require_relative './service/address_template'
+require_relative './service/action'
+require_relative './service/machine_create'
+require_relative './service/address'
+require_relative './service/credential'
+require_relative './service/network_port_template'
+require_relative './service/machine_image_create'
+require_relative './service/address_create'
+require_relative './service/network_template'
+require_relative './service/disk'
+require_relative './service/machine_volume'
+require_relative './service/resource_metadata'
diff --git a/server/lib/cimi/service/action.rb b/server/lib/cimi/service/action.rb
new file mode 100644
index 0000000..9503704
--- /dev/null
+++ b/server/lib/cimi/service/action.rb
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::Action < CIMI::Service::Base
+
+  def operation
+    action.split('/').last.strip.intern
+  end
+end
diff --git a/server/lib/cimi/service/address.rb b/server/lib/cimi/service/address.rb
new file mode 100644
index 0000000..f883c15
--- /dev/null
+++ b/server/lib/cimi/service/address.rb
@@ -0,0 +1,56 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::Address < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id==:all
+      addresses = context.driver.addresses(context.credentials)
+      addresses.map{|addr| from_address(addr, context)}
+    else
+      address = context.driver.address(context.credentials, {:id=>id})
+      from_address(address, context)
+    end
+  end
+
+  def self.delete!(id, context)
+    context.driver.delete_address(context.credentials, id)
+    self.new(context, :values => { :id => id }).destroy
+  end
+
+  private
+
+  def self.from_address(address, context)
+    self.new(context, :values => {
+      :name => address.id,
+      :id => context.address_url(address.id),
+      :description => "Address #{address.id}",
+      :ip => address.id,
+      :allocation => "dynamic",
+      :default_gateway => "unknown",
+      :dns => "unknown",
+      :protocol => protocol_from_address(address.id),
+      :mask => "unknown",
+      :resource => (address.instance_id) ? {:href=> context.machine_url(address.instance_id)} : nil,
+      :network => nil
+    })
+  end
+
+  def self.protocol_from_address(address)
+    addr = IPAddr.new(address)
+    addr.ipv4? ? "ipv4" : "ipv6"
+  end
+
+end
diff --git a/server/lib/cimi/service/address_create.rb b/server/lib/cimi/service/address_create.rb
new file mode 100644
index 0000000..20bda09
--- /dev/null
+++ b/server/lib/cimi/service/address_create.rb
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::AddressCreate < CIMI::Service::Base
+
+  def create
+    template = resolve(address_template)
+
+    params = {
+      :name => name,
+      :description => description,
+      :address_template => template,
+      :env => context # FIXME: We should not pass the context to the driver (!)
+    }
+
+    unless context.driver.respond_to? :create_address
+       raise Deltacloud::Exceptions.exception_from_status(
+         501,
+         "Creating Address is not supported by the current driver"
+       )
+    end
+
+    address = context.driver.create_address(context.credentials, params)
+
+    result = CIMI::Service::Address.from_address(address, context)
+    result.name = name if name
+    result.description = description if description
+    result.property = property if property
+    result.save
+    result
+  end
+
+end
diff --git a/server/lib/cimi/service/address_template.rb b/server/lib/cimi/service/address_template.rb
new file mode 100644
index 0000000..2a5a0d3
--- /dev/null
+++ b/server/lib/cimi/service/address_template.rb
@@ -0,0 +1,71 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::AddressTemplate < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id==:all
+      if context.driver.respond_to? :address_templates
+        context.driver.address_templates(context.credentials, {:env=>context})
+      else
+        current_db.address_templates.map { |t| from_db(t, context) }
+      end
+    else
+      if context.driver.respond_to? :address_template
+        context.driver.address_template(context.credentials, :id => id, :env=>context)
+      else
+        template = current_db.address_templates_dataset.first(:id => id)
+        raise CIMI::Model::NotFound unless template
+        from_db(template, context)
+      end
+    end
+  end
+
+  def self.delete!(id, context)
+    current_db.address_templates.first(:id => id).destroy
+  end
+
+  protected
+  def attributes_to_copy
+    super + [ :ip, :hostname, :allocation, :default_gateway,
+              :dns, :protocol, :mask ]
+  end
+
+  private
+
+  def self.from_db(model, context)
+    self.new(context, :values => {
+      :id => context.address_template_url(model.id),
+      :name => model.name,
+      :description => model.description,
+      :ip => model.ip,
+      :hostname => model.hostname,
+      :allocation => model.allocation,
+      :default_gateway => model.default_gateway,
+      :dns => model.dns,
+      :protocol => model.protocol,
+      :mask => model.mask,
+      :property => (model.ent_properties ? JSON::parse(model.ent_properties) :  nil),
+      :operations => [
+        {
+          :href => context.destroy_address_template_url(model.id),
+          :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
+        }
+      ]
+    })
+  end
+
+
+end
diff --git a/server/lib/cimi/service/address_template_create.rb b/server/lib/cimi/service/address_template_create.rb
new file mode 100644
index 0000000..01566ab
--- /dev/null
+++ b/server/lib/cimi/service/address_template_create.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::AddressTemplateCreate < CIMI::Service::Base
+
+  def create
+    new_template = context.current_db.add_address_template(
+      :name => name,
+      :description => description,
+      :hostname => hostname,
+      :ip => ip,
+      :allocation => allocation,
+      :default_gateway => default_gateway,
+      :dns => dns,
+      :protocol => protocol,
+      :mask => mask,
+      :ent_properties => property.to_json
+    )
+    CIMI::Service::AddressTemplate.from_db(new_template, context)
+  end
+
+end
diff --git a/server/lib/cimi/service/cloud_entry_point.rb b/server/lib/cimi/service/cloud_entry_point.rb
new file mode 100644
index 0000000..5029e12
--- /dev/null
+++ b/server/lib/cimi/service/cloud_entry_point.rb
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::CloudEntryPoint < CIMI::Service::Base
+
+  def self.create(context)
+    self.new(context, :values => entities(context).merge({
+      :name => context.driver.name,
+      :description => "Cloud Entry Point for the Deltacloud #{context.driver.name} driver",
+      :driver => context.driver.name,
+      :provider => context.current_provider,
+      :id => context.cloudEntryPoint_url,
+      :base_uri => context.base_uri + "/",
+      :created => Time.now.xmlschema
+    }))
+  end
+
+  # Return an Hash of the CIMI root entities used in CloudEntryPoint
+  def self.entities(context)
+    CIMI::Collections.modules(:cimi).inject({}) do |supported_entities, m|
+      m.collections.each do |c|
+        index_operation_capability = c.operation(:index).required_capability
+        next if m.settings.respond_to?(:capability) and !m.settings.capability(index_operation_capability)
+        supported_entities[c.collection_name.to_s] = { :href => context.send(:"#{c.collection_name}_url") }
+      end
+      supported_entities
+    end
+  end
+
+  def entities
+    @attribute_values.clone.delete_if { |key, value| !value.respond_to? :href }
+  end
+
+end
diff --git a/server/lib/cimi/service/credential.rb b/server/lib/cimi/service/credential.rb
new file mode 100644
index 0000000..c48f372
--- /dev/null
+++ b/server/lib/cimi/service/credential.rb
@@ -0,0 +1,52 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::Credential < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id == :all
+      return [] unless context.driver.respond_to?(:keys)
+      keys = context.driver.keys(context.credentials)
+      keys.map { |key| from_key(key, context) }
+    else
+      key = context.driver.key(context.credentials, :id => id)
+      from_key(key, context)
+    end
+  end
+
+  def self.create_from_xml(body, context)
+    credential = Credential.from_xml(body)
+    key = context.driver.create_key(context.credentials, :key_name => credential.name)
+    from_key(key, context)
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_key(context.credentials, :id => id)
+  end
+
+  private
+
+  def self.from_key(key, context)
+    self.new(context, :values => {
+      :name => key.id,
+      :username => key.username,
+      :password => key.is_password? ? key.password : key.fingerprint,
+      :key => key.is_key? ? key.pem_rsa_key : nil,
+      :id => context.credential_url(key.id),
+      :created => Time.now.xmlschema
+    })
+  end
+
+end
diff --git a/server/lib/cimi/service/credential_create.rb b/server/lib/cimi/service/credential_create.rb
new file mode 100644
index 0000000..3290596
--- /dev/null
+++ b/server/lib/cimi/service/credential_create.rb
@@ -0,0 +1,38 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::CredentialCreate < CIMI::Service::Base
+
+  def create
+    unless context.driver.respond_to? :create_key
+       raise Deltacloud::Exceptions.exception_from_status(
+         501,
+         "Creating Credential is not supported by the current driver"
+       )
+    end
+
+    template = resolve(credential_template)
+
+    key = context.driver.create_key(context.credentials, :key_name => name)
+
+    result = CIMI::Service::Credential.from_key(key, context)
+    result.name = name if name
+    result.description = description if description
+    result.property = property if property
+    result.save
+    result
+  end
+
+end
diff --git a/server/lib/cimi/service/credential_template.rb b/server/lib/cimi/service/credential_template.rb
new file mode 100644
index 0000000..513160d
--- /dev/null
+++ b/server/lib/cimi/service/credential_template.rb
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::CredentialTemplate < CIMI::Service::Base
+
+  # FIXME: TBD
+
+end
diff --git a/server/lib/cimi/service/disk.rb b/server/lib/cimi/service/disk.rb
new file mode 100644
index 0000000..1af908e
--- /dev/null
+++ b/server/lib/cimi/service/disk.rb
@@ -0,0 +1,80 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::Disk < CIMI::Service::Base
+
+  def self.find(instance, machine_config, context, id=:all)
+    if id == :all
+      name = instance.id+"_disk_" #assuming one disk for now...
+
+      if machine_config
+        mach_config_disks = machine_config.disks
+        return mach_config_disks.map do |d|
+          self.new(context, :values => {
+            :id => context.machine_url(instance.id) + "/disks/#{name}#{d[:capacity]}",
+            :name => "#{name}#{d[:capacity]}",
+            :description => "Disk for Machine #{instance.id}",
+            :created => instance.launch_time.nil? ?
+            Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
+            :capacity => d[:capacity]
+          })
+        end
+      else
+        if instance.instance_profile.override? :storage
+          capacity = context.to_kibibyte(instance.instance_profile.storage, 'MB')
+        else
+          hw_profile = context.driver.hardware_profile(
+            context.credentials,
+            :id => instance.instance_profile.name
+          )
+          if hw_profile.storage
+            capacity = context.to_kibibyte(hw_profile.storage.value, 'MB')
+          end
+        end
+
+        return [] unless capacity
+
+        [self.new(context, :values => {
+          :id => context.machine_url(instance.id)+"/disks/#{name}#{capacity}",
+          :name => name + capacity.to_s,
+          :description => "Disk for Machine #{instance.id}",
+          :created => instance.launch_time.nil? ?
+            Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
+          :capacity => capacity
+        })]
+      end
+    else
+    end
+  end
+
+  def self.collection_for_instance(instance_id, context)
+    instance = context.driver.instance(context.credentials, :id => instance_id)
+    disks = find(instance, nil, context)
+    unless CIMI::Model.const_defined?('DiskCollection')
+      collection_class = CIMI::Model::Collection.generate(self)
+    else
+      collection_class = CIMI::Model::DiskCollection
+    end
+    collection_class.new(context, :values => {
+      :id => context.url("/machines/#{instance_id}/disks"),
+      :name => 'default',
+      :count => disks.size,
+      :description => "Disk collection for Machine #{instance_id}",
+      :entries => disks
+    })
+  end
+
+
+end
diff --git a/server/lib/cimi/service/forwarding_group.rb b/server/lib/cimi/service/forwarding_group.rb
new file mode 100644
index 0000000..ef12350
--- /dev/null
+++ b/server/lib/cimi/service/forwarding_group.rb
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::ForwardingGroup < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.forwarding_groups(context.credentials, {:env=>context})
+    else
+      context.driver.forwarding_groups(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end
diff --git a/server/lib/cimi/service/forwarding_group_template.rb b/server/lib/cimi/service/forwarding_group_template.rb
new file mode 100644
index 0000000..32e7388
--- /dev/null
+++ b/server/lib/cimi/service/forwarding_group_template.rb
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::ForwardingGroupTemplate < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.forwarding_group_templates(context.credentials, {:env=>context})
+    else
+      context.driver.forwarding_group_templates(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end
diff --git a/server/lib/cimi/service/machine.rb b/server/lib/cimi/service/machine.rb
index 72e5346..7112486 100644
--- a/server/lib/cimi/service/machine.rb
+++ b/server/lib/cimi/service/machine.rb
@@ -52,19 +52,19 @@ class CIMI::Service::Machine < CIMI::Service::Base
   def self.attach_volume(volume, location, context)
     context.driver.attach_storage_volume(context.credentials,
      {:id=>volume, :instance_id=>context.params[:id], :device=>location})
-    CIMI::Model::MachineVolume.find(context.params[:id], context, volume)
+    CIMI::Service::MachineVolume.find(context.params[:id], context, volume)
   end
 
   #returns the machine_volume_collection for the given machine
   def self.detach_volume(volume, location, context)
     context.driver.detach_storage_volume(context.credentials,
      {:id=>volume, :instance_id=>context.params[:id], :device=>location})
-    CIMI::Model::MachineVolume.collection_for_instance(context.params[:id], context)
+    CIMI::Service::MachineVolume.collection_for_instance(context.params[:id], context)
   end
 
   def self.from_instance(instance, context)
     cpu =  memory = (instance.instance_profile.id == "opaque")? "n/a" : nil
-    machine_conf = CIMI::Model::MachineConfiguration.find(instance.instance_profile.name, context)
+    machine_conf = CIMI::Service::MachineConfiguration.find(instance.instance_profile.name, context)
     machine_spec = {
       :name => instance.name,
       :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time.to_s).xmlschema,
@@ -78,10 +78,10 @@ class CIMI::Service::Machine < CIMI::Service::Base
       :operations => convert_instance_actions(instance, context)
     }
     if context.expand? :disks
-      machine_spec[:disks] = CIMI::Model::Disk.find(instance, machine_conf, context, :all)
+      machine_spec[:disks] = CIMI::Service::Disk.find(instance, machine_conf, context, :all)
     end
     if context.expand? :volumes
-      machine_spec[:volumes] = CIMI::Model::MachineVolume.find(instance.id, context, :all)
+      machine_spec[:volumes] = CIMI::Service::MachineVolume.find(instance.id, context, :all)
     end
     machine_spec[:realm] = instance.realm_id if instance.realm_id
     machine_spec[:machine_image] = { :href => context.machine_image_url(instance.image_id) } if instance.image_id
@@ -102,14 +102,14 @@ class CIMI::Service::Machine < CIMI::Service::Base
   def self.convert_instance_cpu(profile, context)
     cpu_override = profile.overrides.find { |p, v| p == :cpu }
     if cpu_override.nil?
-      CIMI::Model::MachineConfiguration.find(profile.id, context).cpu
+      CIMI::Service::MachineConfiguration.find(profile.id, context).cpu
     else
       cpu_override[1]
     end
   end
 
   def self.convert_instance_memory(profile, context)
-    machine_conf = CIMI::Model::MachineConfiguration.find(profile.name, context)
+    machine_conf = CIMI::Service::MachineConfiguration.find(profile.name, context)
     memory_override = profile.overrides.find { |p, v| p == :memory }
     memory_override.nil? ? machine_conf.memory.to_i : context.to_kibibyte(memory_override[1].to_i,"MB")
   end
diff --git a/server/lib/cimi/service/machine_configuration.rb b/server/lib/cimi/service/machine_configuration.rb
new file mode 100644
index 0000000..d4ddf20
--- /dev/null
+++ b/server/lib/cimi/service/machine_configuration.rb
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::MachineConfiguration < CIMI::Service::Base
+
+  def self.find(id, context)
+    profiles = []
+    if id == :all
+      profiles = context.driver.hardware_profiles(context.credentials)
+      profiles.map { |profile| from_hardware_profile(profile, context) }.compact
+    else
+      profile = context.driver.hardware_profile(context.credentials, id)
+      from_hardware_profile(profile, context)
+    end
+  end
+
+  private
+  def self.from_hardware_profile(profile, context)
+    # We accept just profiles with all properties set
+    return unless profile.memory or profile.cpu or profile.storage
+    memory = profile.memory ?
+      context.to_kibibyte((profile.memory.value || profile.memory.default), profile.memory.unit) : nil
+    cpu = (profile.cpu ? (profile.cpu.value || profile.cpu.default) : nil )
+    storage = profile.storage ?
+      context.to_kibibyte((profile.storage.value || profile.storage.default), profile.storage.unit) :  nil
+    machine_hash = {
+      :name => profile.name,
+      :description => "Machine Configuration with #{memory} KiB of memory and #{cpu} CPU",
+      :cpu => ( cpu.to_i.to_s if cpu ) ,
+      :created => Time.now.xmlschema,  # FIXME: DC hardware_profile has no mention about created_at
+      :memory => (memory if memory),
+      :disks => ( [ {
+        :capacity => storage,
+        :format => (profile.storage.respond_to?(:format) ? profile.storage.format : "unknown")  }
+      ] if storage ), # no format attr for hwp - may be added if providers support...,
+      :id => context.machine_configuration_url(profile.id)
+    }
+    self.new(context, :values => machine_hash)
+  end
+
+
+end
diff --git a/server/lib/cimi/service/machine_create.rb b/server/lib/cimi/service/machine_create.rb
new file mode 100644
index 0000000..1e5b637
--- /dev/null
+++ b/server/lib/cimi/service/machine_create.rb
@@ -0,0 +1,49 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::MachineCreate < CIMI::Service::Base
+
+  def create
+    params = {}
+    if machine_template.href
+      template = resolve(machine_template)
+      params[:hwp_id] = ref_id(template.machine_config.href)
+      params[:initial_state] = template.initial_state
+      image_id = ref_id(template.machine_image.href)
+    else
+      # FIXME: What if either of these href's isn't there ? What if the user
+      # tries to override some aspect of the machine_config/machine_image ?
+      params[:hwp_id] = ref_id(machine_template.machine_config.href)
+      params[:initial_state] = machine_template.initial_state
+      image_id = ref_id(machine_template.machine_image.href)
+      if machine_template.credential.href
+        params[:keyname] = ref_id(machine_template.credential.href)
+      end
+    end
+
+    params[:name] = name if name
+    params[:realm_id] = realm if realm
+    instance = context.driver.create_instance(context.credentials, image_id, params)
+
+    result = CIMI::Service::Machine::from_instance(instance, context)
+    result.name = name if name
+    result.description = description if description
+    result.property = property if property
+    result.save
+    result
+  end
+
+
+end
diff --git a/server/lib/cimi/service/machine_image.rb b/server/lib/cimi/service/machine_image.rb
index dad26a8..17d9220 100644
--- a/server/lib/cimi/service/machine_image.rb
+++ b/server/lib/cimi/service/machine_image.rb
@@ -15,10 +15,6 @@
 
 class CIMI::Service::MachineImage < CIMI::Service::Base
 
-  def initialize(ctx, opts)
-    super
-  end
-
   def self.find(id, context)
     images = []
     if id == :all
@@ -44,7 +40,7 @@ class CIMI::Service::MachineImage < CIMI::Service::Base
 
   def self.delete!(image_id, context)
     context.driver.destroy_image(context.credentials, image_id)
-    new(:id => image_id).destroy
+    self.new(context, :values => { :id => image_id }).destroy
   end
 
 
diff --git a/server/lib/cimi/service/machine_image_create.rb b/server/lib/cimi/service/machine_image_create.rb
new file mode 100644
index 0000000..7cd1a01
--- /dev/null
+++ b/server/lib/cimi/service/machine_image_create.rb
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::MachineImageCreate < CIMI::Service::Base
+
+  def create
+    params = {
+      :id => context.href_id(image_location, :machines),
+      :name => name,
+      :description => description
+    }
+
+    img = context.driver.create_image(context.credentials, params)
+
+    result = CIMI::Service::MachineImage.from_image(img, context)
+    result.name = name if name
+    result.description = description if description
+    result.property = property if property
+    result.save
+    result
+  end
+
+end
diff --git a/server/lib/cimi/service/machine_template.rb b/server/lib/cimi/service/machine_template.rb
new file mode 100644
index 0000000..e790e89
--- /dev/null
+++ b/server/lib/cimi/service/machine_template.rb
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::MachineTemplate < CIMI::Service::Base
+
+  def initialize(ctx, opts)
+    super
+  end
+
+  class << self
+    def find(id, context)
+      if id == :all
+        current_db.machine_templates.map { |t| from_db(t, context) }
+      else
+        template = current_db.machine_templates_dataset.first(:id => id)
+        raise CIMI::Model::NotFound unless template
+        from_db(template, context)
+      end
+    end
+
+    def delete!(id, context)
+      current_db.machine_templates.first(:id => id).destroy
+    end
+
+    def from_db(model, context)
+      self.new(context, :values => {
+        :id => context.machine_template_url(model.id),
+        :name => model.name,
+        :description => model.description,
+        :machine_config => { :href => model.machine_config },
+        :machine_image => { :href => model.machine_image },
+        :realm => model.realm,
+        :property => (model.ent_properties ? JSON::parse(model.ent_properties) :  nil),
+        :created => Time.parse(model.created_at.to_s).xmlschema,
+        :operations => [
+          {
+            :href => context.destroy_machine_template_url(model.id),
+            :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
+          }
+        ]
+      })
+    end
+  end
+
+  protected
+  def attributes_to_copy
+    super + [ :machine_config, :machine_image ]
+  end
+end
diff --git a/server/lib/cimi/service/machine_template_create.rb b/server/lib/cimi/service/machine_template_create.rb
new file mode 100644
index 0000000..a47aa6c
--- /dev/null
+++ b/server/lib/cimi/service/machine_template_create.rb
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::MachineTemplateCreate < CIMI::Service::Base
+
+  def create
+    new_template = self.class.current_db.add_machine_template(
+      :name => name,
+      :description => description,
+      :machine_config => machine_config.href,
+      :machine_image => machine_image.href,
+      :ent_properties => property.to_json
+    )
+    CIMI::Service::MachineTemplate.from_db(new_template, context)
+  end
+
+end
diff --git a/server/lib/cimi/service/machine_volume.rb b/server/lib/cimi/service/machine_volume.rb
new file mode 100644
index 0000000..77c545b
--- /dev/null
+++ b/server/lib/cimi/service/machine_volume.rb
@@ -0,0 +1,74 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::MachineVolume < CIMI::Service::Base
+
+  def self.find(instance_id, context, id=:all)
+    if id == :all
+      volumes = context.driver.storage_volumes(context.credentials)
+      volumes.inject([]) do |attached, vol|
+        id = context.machine_url(instance_id)+"/volumes/#{vol.id}"
+        attached <<  self.new(context, :values => {
+          :id => id,
+          :name => vol.id,
+          :description => "MachineVolume #{vol.id} for Machine #{instance_id}",
+          :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+          :initial_location => vol.device,
+          :volume => {:href=>context.volume_url(vol.id)},
+          :operations => [{:href=>id, :rel => "delete" }]
+        }) if vol.instance_id == instance_id
+        attached
+      end
+    else
+      vol = context.driver.storage_volume(context.credentials, {:id=>id})
+      id = context.machine_url(instance_id)+"/volumes/#{vol.id}"
+      raise CIMI::Model::NotFound unless vol.instance_id == instance_id
+      self.new(context, :values => {
+        :id => id,
+        :name => vol.id,
+        :description => "MachineVolume #{vol.id} for Machine #{instance_id}",
+        :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+        :initial_location => vol.device,
+        :volume => {:href=>context.volume_url(vol.id)},
+        :operations => [{:href=>id, :rel => "delete" }]
+      })
+    end
+  end
+
+  def self.find_to_attach_from_xml(xml_in, context)
+    xml = XmlSimple.xml_in(xml_in)
+    vol_id = xml["volume"].first["href"].split("/").last
+    location = xml["initialLocation"].first.strip
+    [vol_id, location]
+  end
+
+  def self.find_to_attach_from_json(json_in, context)
+    json = JSON.parse(json_in)
+    vol_id = json["volume"]["href"].split("/").last
+    location = json["initialLocation"]
+    [vol_id, location]
+  end
+
+
+  def self.collection_for_instance(instance_id, context)
+    machine_volumes = self.find(instance_id, context)
+    volumes_url = context.url("/machines/#{instance_id}/volumes")
+    # FIXME: Really ???
+    attach_url = volumes_url.singularize+"_attach"
+    CIMI::Model::MachineVolume.list(volumes_url, machine_volumes, :add_url => attach_url)
+  end
+
+
+end
diff --git a/server/lib/cimi/service/network.rb b/server/lib/cimi/service/network.rb
new file mode 100644
index 0000000..a58aa1e
--- /dev/null
+++ b/server/lib/cimi/service/network.rb
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::Network < CIMI::Service::Base
+
+  def self.find(id, context)
+    networks=[]
+    if id==:all
+      networks = context.driver.networks(context.credentials, {:env=>context})
+    else
+      networks = context.driver.networks(context.credentials, {:id=>id, :env=>context})
+    end
+    if context.expand? :networkPorts
+      networks.each do |network|
+        network.network_ports = CIMI::Service::NetworkPort.collection_for_network(network.id, context)
+      end
+    end
+    networks
+  end
+
+
+  def self.delete!(id, context)
+    context.driver.delete_network(context.credentials, id)
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_network", context.credentials, self.name)
+        block.callback :success
+      else
+        raise "Operation #{action.name} failed to execute on the Network #{self.name} "
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+
+end
diff --git a/server/lib/cimi/service/network_configuration.rb b/server/lib/cimi/service/network_configuration.rb
new file mode 100644
index 0000000..a133c94
--- /dev/null
+++ b/server/lib/cimi/service/network_configuration.rb
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::NetworkConfiguration < CIMI::Service::Base
+
+  def self.find(id, context)
+    network_configs = []
+    if id==:all
+      network_configs = context.driver.network_configurations(context.credentials, {:env=>context})
+    else
+      network_configs = context.driver.network_configurations(context.credentials, {:env=>context, :id=>id})
+    end
+    network_configs
+  end
+
+  def self.create_from_xml(request_body, context)
+    warn "This method should go into NetworkConfigurationCreate model"
+  end
+
+  def self.create_from_json(request_body, context)
+    warn "This method should go into NetworkConfigurationCreate model"
+  end
+
+end
diff --git a/server/lib/cimi/service/network_create.rb b/server/lib/cimi/service/network_create.rb
new file mode 100644
index 0000000..f191833
--- /dev/null
+++ b/server/lib/cimi/service/network_create.rb
@@ -0,0 +1,39 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::NetworkCreate < CIMI::Service::Base
+
+  def create
+    if network_template.href?
+      template = resolve(network_template)
+      network_config = resolve(template.network_config)
+      forwarding_group = resolve(template.forwarding_group)
+    else
+      network_config = CIMI::Service::NetworkConfiguration.find(context.href_id(network_template.network_config.href, :network_configurations), context)
+      forwarding_group = CIMI::Service::ForwardingGroup.find(context.href_id(network_template.forwarding_group.href, :forwarding_groups), context)
+    end
+    params = {
+      :network_config => network_config,
+      :forwarding_group => forwarding_group,
+      :name => name,
+      :description => description,
+      :env => context # FIXME: We should not pass the context to the driver (!)
+    }
+    network = context.driver.create_network(context.credentials, params)
+    network.property = property if property
+    network.save
+    network
+  end
+end
diff --git a/server/lib/cimi/service/network_port.rb b/server/lib/cimi/service/network_port.rb
new file mode 100644
index 0000000..d400411
--- /dev/null
+++ b/server/lib/cimi/service/network_port.rb
@@ -0,0 +1,97 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::NetworkPort < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.network_ports(context.credentials, {:env=>context})
+    else
+      context.driver.network_ports(context.credentials, {:id=>id, :env=>context})
+    end
+  end
+
+  # FIXME: This should go into NetworkPortCreate model
+  #
+  def self.create(request_body, context, type)
+    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false, "NormaliseSpace"=>2}) : JSON.parse(request_body)
+    if input["networkPortTemplate"]["href"] #template by reference
+      network_port_config, network = get_by_reference(input, context)
+    else
+      if input["networkPortTemplate"]["networkPortConfig"]["href"] # configuration by reference
+        network_port_config = CIMI::Service::NetworkPortConfiguration.find(context.href_id(input["networkPortTemplate"]["networkPortConfig"]["href"],:network_port_configurations), context)
+      else #configuration by value
+        network_port_config = get_by_value(request_body, type)
+      end
+      network = CIMI::Service::Network.find(context.href_id(input["networkPortTemplate"]["network"]["href"], :networks), context)
+    end
+    params = {:network_port_config => network_port_config, :network => network, :name=>input["name"], :description=>input["description"], :env=>context}
+    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
+    context.driver.create_network_port(context.credentials, params)
+  end
+
+  def self.delete!(id, context)
+    context.driver.delete_network_port(context.credentials, id)
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_network_port", context.credentials, self.name)
+        block.callback :success
+      else
+        raise "Operation #{action.name} failed to execute on the NetworkPort #{self.name} "
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+  def self.collection_for_network(network_id, context)
+    net_url = context.network_url(network_id)
+    network_ports = CIMI::Service::NetworkPort.all(context)
+    ports_collection = network_ports.inject([]){|res, current| res << current if current.network.href == net_url ; res}
+    CIMI::Service::NetworkPortCollection.new(context, :values => {
+      :id => net_url+"/network_ports",
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} NetworkPortCollection",
+      :count => ports_collection.size,
+      :network_ports => ports_collection
+    })
+  end
+
+  private
+
+  # FIXME: Are the methods below really needed???
+
+  def self.get_by_reference(input, context)
+    network_port_template = CIMI::Service::NetworkPortTemplate.find(context.href_id(input["networkPortTemplate"]["href"], :network_port_templates), context)
+    network_port_config = CIMI::Service::NetworkPortConfiguration.find(context.href_id(network_port_template.network_port_config.href, :network_port_configurations), context)
+    network = CIMI::Service::Network.find(context.href_id(network_port_template.network.href, :networks), context)
+    return network_port_config, network
+  end
+
+  def self.get_by_value(request_body, type)
+    if type == :xml
+      xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
+      network_port_config = CIMI::Service::NetworkPortConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["networkPortTemplate"][0]["networkPortConfig"][0]))
+    else
+     json = JSON.parse(request_body)
+      network_port_config = CIMI::Service::NetworkPortConfiguration.from_json(JSON.generate(json["networkPortTemplate"]["networkPortConfig"]))
+    end
+  end
+
+
+end
diff --git a/server/lib/cimi/service/network_port_configuration.rb b/server/lib/cimi/service/network_port_configuration.rb
new file mode 100644
index 0000000..2d5c1ba
--- /dev/null
+++ b/server/lib/cimi/service/network_port_configuration.rb
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::NetworkPortConfiguration < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.network_port_configurations(context.credentials, {:env=>context})
+    else
+      context.driver.network_port_configurations(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end
diff --git a/server/lib/cimi/service/network_port_template.rb b/server/lib/cimi/service/network_port_template.rb
new file mode 100644
index 0000000..9f60493
--- /dev/null
+++ b/server/lib/cimi/service/network_port_template.rb
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::NetworkPortTemplate < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.network_port_templates(context.credentials, {:env=>context})
+    else
+      context.driver.network_port_templates(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end
diff --git a/server/lib/cimi/service/network_template.rb b/server/lib/cimi/service/network_template.rb
new file mode 100644
index 0000000..afe79f6
--- /dev/null
+++ b/server/lib/cimi/service/network_template.rb
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::NetworkTemplate < CIMI::Service::Base
+
+  def self.find(id, context)
+    network_templates = []
+    if id==:all
+      network_templates = context.driver.network_templates(context.credentials, {:env=>context})
+    else
+      network_templates = context.driver.network_templates(context.credentials, {:env=>context, :id=>id})
+    end
+    network_templates
+  end
+
+end
diff --git a/server/lib/cimi/service/resource_metadata.rb b/server/lib/cimi/service/resource_metadata.rb
new file mode 100644
index 0000000..23924fb
--- /dev/null
+++ b/server/lib/cimi/service/resource_metadata.rb
@@ -0,0 +1,110 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+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
+    else
+      resource_class = CIMI::Model.const_get("#{id.camelize}")
+      resource_metadata_for(resource_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
+    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
+    })
+  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
+  end
+
+
+end
diff --git a/server/lib/cimi/service/system.rb b/server/lib/cimi/service/system.rb
new file mode 100644
index 0000000..daad428
--- /dev/null
+++ b/server/lib/cimi/service/system.rb
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::System < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id == :all
+      systems = context.driver.systems(context.credentials, {:env=>context})
+    else
+      systems = context.driver.systems(context.credentials, {:env=>context, :id=>id})
+      raise CIMI::Model::NotFound unless systems.first
+      systems.first
+    end
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_system", context.credentials, self.id.split("/").last)
+        block.callback :success
+      else
+        raise "Operation failed to execute on given System"
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_system(context.credentials, id)
+  end
+
+
+end
diff --git a/server/lib/cimi/service/system_template.rb b/server/lib/cimi/service/system_template.rb
new file mode 100644
index 0000000..785f79d
--- /dev/null
+++ b/server/lib/cimi/service/system_template.rb
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::SystemTemplate < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id == :all
+      templates = context.driver.system_templates(context.credentials, {:env=>context})
+    else
+      templates = context.driver.system_templates(context.credentials, {:env=>context, :id=>id})
+      raise CIMI::Model::NotFound unless templates.first
+      templates.first
+    end
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_system_template(context.credentials, id)
+  end
+
+end
diff --git a/server/lib/cimi/service/volume.rb b/server/lib/cimi/service/volume.rb
new file mode 100644
index 0000000..2e38691
--- /dev/null
+++ b/server/lib/cimi/service/volume.rb
@@ -0,0 +1,81 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::Volume < CIMI::Service::Base
+
+  def self.find(id, context)
+    creds = context.credentials
+    if id == :all
+      volumes = context.driver.storage_volumes(creds)
+      volumes.collect{ |volume| from_storage_volume(volume, context) }
+    else
+      volume = context.driver.storage_volumes(creds, :id => id).first
+      raise CIMI::Model::NotFound unless volume
+      from_storage_volume(volume, context)
+    end
+  end
+
+  def self.all(context); find(:all, context); end
+
+  def self.delete!(id, context)
+    context.driver.destroy_storage_volume(context.credentials, {:id=>id} )
+    new(context, :values => { :id => id }).destroy
+  end
+
+  def self.find_to_attach_from_json(json_in, context)
+    json = JSON.parse(json_in)
+    json["volumes"].map{|v| {:volume=>self.find(v["volume"]["href"].split("/volumes/").last, context),
+                             :initial_location=>v["initialLocation"]  }}
+  end
+
+  def self.find_to_attach_from_xml(xml_in, context)
+    xml = XmlSimple.xml_in(xml_in)
+    xml["volume"].map{|v| {:volume => self.find(v["href"].split("/volumes/").last, context),
+                           :initial_location=>v["initialLocation"] }}
+  end
+
+  def self.from_storage_volume(volume, context)
+    self.new(context, :values => {
+      :name => volume.id,
+      :created => volume.created.nil? ? nil : Time.parse(volume.created).xmlschema,
+      :id => context.volume_url(volume.id),
+      :capacity => context.to_kibibyte(volume.capacity, 'GB'),
+      :bootable => "false", #fixme ... will vary... ec2 doesn't expose this
+      :snapshots => [], #fixme...
+      :type => 'http://schemas.dmtf.org/cimi/1/mapped',
+      :state => volume.state == 'IN-USE' ? 'AVAILABLE' : volume.state,
+      :meters => [],
+      :operations => [{:href=> context.volume_url(volume.id), :rel => "delete"}]
+    })
+  end
+
+  def self.collection_for_instance(instance_id, context)
+    instance = context.driver.instance(context.credentials, :id => instance_id)
+    volumes = instance.storage_volumes.map do |mappings|
+      mappings.keys.map do |volume_id|
+        from_storage_volume(context.driver.storage_volume(context.credentials, :id => volume_id), context)
+      end
+    end.flatten
+    CIMI::Service::VolumeCollection.new(context, :values => {
+      :id => context.url("/machines/#{instance_id}/volumes"),
+      :name => 'default',
+      :count => volumes.size,
+      :description => "Volume collection for Machine #{instance_id}",
+      :entries => volumes
+    })
+  end
+
+
+end
diff --git a/server/lib/cimi/service/volume_configuration.rb b/server/lib/cimi/service/volume_configuration.rb
new file mode 100644
index 0000000..ebb2c7c
--- /dev/null
+++ b/server/lib/cimi/service/volume_configuration.rb
@@ -0,0 +1,92 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::VolumeConfiguration < CIMI::Service::Base
+
+  # FIXME: These two should go into VolumeConfigurationCreate
+  #
+  def self.create_from_json(body, context)
+    json = JSON.parse(body)
+    new_config = current_db.add_volume_configuration(
+      :name => json['name'],
+      :description => json['description'],
+      :format => json['format'],
+      :capacity => json['capacity'],
+      :ent_properties => (json['properties'] || {}).to_json
+    )
+    from_db(new_config, context)
+  end
+
+  def self.create_from_xml(body, context)
+    xml = XmlSimple.xml_in(body)
+    xml['property'] ||= []
+    new_config = current_db.add_volume_configuration(
+      :name => xml['name'].first,
+      :description => xml['description'].first,
+      :format => xml['format'].first,
+      :capacity => xml['capacity'].first,
+      :ent_properties =>  JSON::dump((xml['property'] || {}).inject({}){ |r, p| r[p['key']]=p['content']; r })
+    )
+    from_db(new_config, context)
+  end
+
+  def self.delete!(id, context)
+    current_db.volume_configurations.first(:id => id).destroy
+  end
+
+  def self.find(id, context)
+    if id==:all
+      if context.driver.respond_to? :volume_configurations
+        context.driver.volume_configurations(context.credentials, {:env=>context})
+      else
+        current_db.volume_configurations.map { |t| from_db(t, context) }
+      end
+    else
+      if context.driver.respond_to? :volume_configuration
+        context.driver.volume_configuration(context.credentials, id, :env=>context)
+      else
+        config = current_db.volume_configurations_dataset.first(:id => id)
+        raise CIMI::Model::NotFound unless config
+        from_db(config, context)
+      end
+    end
+  end
+
+  protected
+  def attributes_to_copy
+    super + [ :format, :capacity ]
+  end
+
+  private
+
+  def self.from_db(model, context)
+    self.new(context, :values => {
+      :id => context.volume_configuration_url(model.id),
+      :name => model.name,
+      :description => model.description,
+      :format => model.format,
+      :capacity => context.to_kibibyte(model.capacity, "GB"),
+      :property => (model.ent_properties ? JSON::parse(model.ent_properties) :  nil),
+      :operations => [
+        {
+          :href => context.destroy_volume_configuration_url(model.id),
+          :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
+        }
+      ]
+    })
+  end
+
+
+end
diff --git a/server/lib/cimi/service/volume_create.rb b/server/lib/cimi/service/volume_create.rb
new file mode 100644
index 0000000..6d9f3d0
--- /dev/null
+++ b/server/lib/cimi/service/volume_create.rb
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::VolumeCreate < CIMI::Service::Base
+
+  def create
+    template = resolve(volume_template)
+    volume_image = resolve(template.volume_image)
+    volume_config = resolve(template.volume_config)
+
+    params = {
+      :name => name,
+      :capacity => volume_config.capacity,
+      :snapshot_id => ref_id(volume_image.id),
+    }
+
+    unless context.driver.respond_to? :create_storage_volume
+       raise Deltacloud::Exceptions.exception_from_status(
+         501,
+         "Creating Volume is not supported by the current driver"
+       )
+    end
+
+    volume = context.driver.create_storage_volume(context.credentials, params)
+
+    result = CIMI::Service::Volume.from_storage_volume(volume, context)
+    result.name = name if name
+    result.description = description if description
+    result.property = property if property
+    result.save
+    result
+  end
+
+
+end
diff --git a/server/lib/cimi/service/volume_image.rb b/server/lib/cimi/service/volume_image.rb
new file mode 100644
index 0000000..5d57368
--- /dev/null
+++ b/server/lib/cimi/service/volume_image.rb
@@ -0,0 +1,44 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::VolumeImage < CIMI::Service::Base
+
+  def self.find(id, context)
+    creds = context.credentials
+    if id == :all
+      snapshots = context.driver.storage_snapshots(creds)
+      snapshots.collect{ |snapshot| from_storage_snapshot(snapshot, context) }
+    else
+      snapshot = context.driver.storage_snapshots(creds, id => :id).first
+      raise CIMI::Model::NotFound unless snapshot
+      from_storage_snapshot(snapshot, context)
+    end
+  end
+
+  def self.delete!(vol_image_id, context)
+    context.driver.destroy_storage_snapshot(context.credentials, {:id=>vol_image_id})
+  end
+
+  def self.from_storage_snapshot(snapshot, context)
+    self.new( context, :values => {
+      :name => snapshot.name,
+      :description => snapshot.description,
+      :created => snapshot.created.nil? ? nil : Time.parse(snapshot.created).xmlschema,
+      :id => context.volume_image_url(snapshot.id),
+      :image_location => {:href=>context.volume_url(snapshot.storage_volume_id)},
+      :bootable => "false"  #FIXME
+    } )
+  end
+end
diff --git a/server/lib/cimi/service/volume_image_create.rb b/server/lib/cimi/service/volume_image_create.rb
new file mode 100644
index 0000000..f75b2ef
--- /dev/null
+++ b/server/lib/cimi/service/volume_image_create.rb
@@ -0,0 +1,42 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::VolumeImageCreate < CIMI::Service::Base
+
+  def create
+    params = {
+      :volume_id => context.href_id(image_location.href, :volumes),
+      :name => name,
+      :description => description
+    }
+
+    unless context.driver.respond_to? :create_storage_snapshot
+      raise Deltacloud::Exceptions.exception_from_status(
+        501,
+        'Creating VolumeImage is not supported by the current driver'
+      )
+    end
+
+    new_snapshot = context.driver.create_storage_snapshot(context.credentials, params)
+    result = CIMI::Service::VolumeImage.from_storage_snapshot(new_snapshot, context)
+    result.name= name unless new_snapshot.name
+    result.description = description unless new_snapshot.description
+    result.property = property if property
+    result.save
+    result
+  end
+
+
+end
diff --git a/server/lib/cimi/service/volume_template.rb b/server/lib/cimi/service/volume_template.rb
new file mode 100644
index 0000000..d95ba72
--- /dev/null
+++ b/server/lib/cimi/service/volume_template.rb
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::VolumeTemplate < CIMI::Service::Base
+
+  def self.find(id, context)
+    if id==:all
+      if context.driver.respond_to? :volume_templates
+        context.driver.volume_templates(context.credentials, {:env=>context})
+      else
+        current_db.volume_templates.map { |t| from_db(t, context) }
+      end
+    else
+      if context.driver.respond_to? :volume_template
+        context.driver.volume_template(context.credentials, id, :env=>context)
+      else
+        template = current_db.volume_templates_dataset.first(:id => id)
+        raise CIMI::Model::NotFound unless template
+        from_db(template, context)
+      end
+    end
+  end
+
+  def self.delete!(id, context)
+    current_db.volume_templates.first(:id => id).destroy
+  end
+
+  def self.from_db(model, context)
+    self.new(context, :values => {
+      :id => context.volume_template_url(model.id),
+      :name => model.name,
+      :description => model.description,
+      :volume_config => {:href => model.volume_config},
+      :volume_image => {:href => model.volume_image},
+      :property => (model.ent_properties ? JSON::parse(model.ent_properties) :  nil),
+      :operations => [
+        {
+          :href => context.destroy_volume_template_url(model.id),
+          :rel => 'http://schemas.dmtf.org/cimi/1/action/delete'
+        }
+      ]
+    })
+  end
+
+  protected
+  def attributes_to_copy
+    super + [ :machine_config, :machine_image ]
+  end
+end
diff --git a/server/lib/cimi/service/volume_template_create.rb b/server/lib/cimi/service/volume_template_create.rb
new file mode 100644
index 0000000..b05e0f4
--- /dev/null
+++ b/server/lib/cimi/service/volume_template_create.rb
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::VolumeTemplateCreate < CIMI::Service::Base
+
+  def create
+    new_template = self.class.current_db.add_volume_template(
+      :name => name,
+      :description => description,
+      :volume_config => volume_config.href,
+      :volume_image => volume_image.href,
+      :ent_properties => property.to_json
+    )
+    CIMI::Service::VolumeTemplate.from_db(new_template, context)
+  end
+
+end
-- 
1.8.1.4


[PATCH 14/14] CIMI: remove unused model methods

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

Collection.all and Resource.all_uri do not make sense any more since they
ultimately depend on find, which is now a service method.
---
 server/lib/cimi/models/collection.rb | 6 ------
 server/lib/cimi/models/resource.rb   | 6 ------
 2 files changed, 12 deletions(-)

diff --git a/server/lib/cimi/models/collection.rb b/server/lib/cimi/models/collection.rb
index cc95ab7..b06a1e9 100644
--- a/server/lib/cimi/models/collection.rb
+++ b/server/lib/cimi/models/collection.rb
@@ -130,11 +130,5 @@ module CIMI::Model
       end
       collection_class.new(params)
     end
-
-    def all(context)
-      find :all, context
-    end
-
   end
-
 end
diff --git a/server/lib/cimi/models/resource.rb b/server/lib/cimi/models/resource.rb
index 246b135..9f5bb66 100644
--- a/server/lib/cimi/models/resource.rb
+++ b/server/lib/cimi/models/resource.rb
@@ -89,12 +89,6 @@ module CIMI
           end
         end
 
-        # Return Array of links to current CIMI object
-        #
-        def all_uri(context)
-          self.all(context).map { |e| { :href => e.id } }
-        end
-
         # Construct a new object from the XML representation +xml+
         def from_xml(text)
           xml = XmlSimple.xml_in(text, :force_content => true)
-- 
1.8.1.4


[PATCH 01/14] CIMI Models: rename hash in DSL to hash_map

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

Since 'hash' is used for putting objects into Hash, overriding it as a
class method causes surprises when a class is used as a hash key.
---
 server/lib/cimi/models/base.rb            | 2 +-
 server/lib/cimi/models/schema.rb          | 2 +-
 server/lib/cimi/models/system_template.rb | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index e8c1104..a207bed 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -121,7 +121,7 @@ module CIMI::Model
     # Common attributes for all resources
     #
     text :id, :name, :description, :created, :updated
-    hash :property
+    hash_map :property
 
     def initialize(values = {})
       super(values)
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index 4ce16b9..b4e9377 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -461,7 +461,7 @@ class CIMI::Model::Schema
       add_attributes!([name, opts], Ref)
     end
 
-    def hash(name)
+    def hash_map(name)
       add_attributes!([name, {}], Hash)
     end
 
diff --git a/server/lib/cimi/models/system_template.rb b/server/lib/cimi/models/system_template.rb
index 09cd9b0..6a6e1f2 100644
--- a/server/lib/cimi/models/system_template.rb
+++ b/server/lib/cimi/models/system_template.rb
@@ -19,7 +19,7 @@ class CIMI::Model::SystemTemplate < CIMI::Model::Base
 
   array :component_descriptors do
     text :name, :description
-    hash :properties
+    hash_map :properties
     text :type
     #component_template, comprises:
 #    struct :machine_template, :class => CIMI::Model::MachineTemplate
-- 
1.8.1.4


Re: RFC: Separate CIMI (de)serialization from server functionality (rev 3)

Posted by David Lutterkort <lu...@redhat.com>.
On Wed, 2013-03-13 at 17:33 -0700, lutter@redhat.com wrote:
> This is the third take on splitting server-side functionality out of our
> models. As in previous attempts, CIMI::Model is now solely concerned with
> (se)serialization, whereas CIMI::Service does all the actual server-side
> functionality.
> 
> FWIW, the unit and blackbox tests all pass for me with this patch series
> ...
> 
> Also recorded as http://tracker.deltacloud.org/set/389

Actually, the RFC in the subject line was a mistake; I would like to
commit these unless there are good reasons not to.

David



[PATCH 07/14] CIMI: Added Service::Base#parse method

Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>

Make possible to call .parse on Service models from
Rabbit collections.

Signed-off-by: Michal fojtik <mf...@redhat.com>
TrackedAt: http://tracker.deltacloud.org/patch/a16895d3bb6ab3596fb77fee96d041e01c3a1747
---
 server/lib/cimi/service/base.rb | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/server/lib/cimi/service/base.rb b/server/lib/cimi/service/base.rb
index 8daa183..fa845d0 100644
--- a/server/lib/cimi/service/base.rb
+++ b/server/lib/cimi/service/base.rb
@@ -50,6 +50,13 @@ module CIMI::Service
           define_method(:"#{name}=") { |newval| self[name] = newval }
         end
       end
+
+      def parse(context)
+        req = context.request
+        model = model_class.parse(req.body, req.content_type)
+        new(context, :model => model)
+      end
+
     end
 
     def initialize(context, opts)
-- 
1.8.1.4


[PATCH 12/14] CIMI::Model::Schema::Ref: do not support looking up the referenced object

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

This now depends on service objects and can therefore not be used from models
---
 server/lib/cimi/models/schema.rb | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index b6651a7..5a2049b 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -191,20 +191,6 @@ class CIMI::Model::Schema
       else
         @klass = Class.new(opts[:class]) do |m|
           scalar :href
-
-          def ref_id(ctx)
-            # FIXME: We should use ctx's routes to split
-            # out the :id
-            href.split('/').last
-          end
-
-          def find(ctx)
-            klass.find(ref_id(ctx), ctx)
-          end
-
-          def klass
-            self.class.superclass
-          end
         end
         CIMI::Model::const_set(refname, @klass)
       end
-- 
1.8.1.4


[PATCH 13/14] CIMI: a very simple test of volume creation

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

---
 server/tests/cimi/collections/volumes_test.rb | 42 +++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 server/tests/cimi/collections/volumes_test.rb

diff --git a/server/tests/cimi/collections/volumes_test.rb b/server/tests/cimi/collections/volumes_test.rb
new file mode 100644
index 0000000..0b55d06
--- /dev/null
+++ b/server/tests/cimi/collections/volumes_test.rb
@@ -0,0 +1,42 @@
+require 'rubygems'
+require 'require_relative' if RUBY_VERSION < '1.9'
+require 'minitest/autorun'
+require_relative './common.rb'
+
+describe CIMI::Collections::Volumes do
+
+  def create_model(model_class, attr)
+    model = model_class.new(attr)
+    svc_class = CIMI::Service::const_get(model_class.name.split('::').last)
+    svc_class.new(nil, :model => model).save
+    model
+  end
+
+  before do
+    def app; run_frontend(:cimi) end
+    authorize 'mockuser', 'mockpassword'
+
+    @config = create_model CIMI::Model::VolumeConfiguration,
+      :id => "http://localhost:3001/cimi/volume_configurations/1",
+      :name => "volume_config",
+      :format => "ext3",
+      :capacity => 1
+
+    @collection = CIMI::Collections.collection(:volumes)
+  end
+
+  def make_volume_create
+    vt = CIMI::Model::VolumeTemplate.new
+    vt.volume_config.href = @config.id
+    CIMI::Model::VolumeCreate.new(:name => "new_cimi_volume_#{Time.now.to_i}",
+         :volume_template => vt)
+  end
+
+  it 'allows creation of a new volume' do
+    vc = make_volume_create
+    post '/cimi/volumes', vc.to_json, "CONTENT_TYPE" => "application/json"
+
+    last_response.status.must_equal 201
+    model.name.must_equal vc.name
+  end
+end
-- 
1.8.1.4


[PATCH 09/14] CIMI: Use CIMI::Service namespace in Rabbit collections

Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>

Signed-off-by: Michal fojtik <mf...@redhat.com>
TrackedAt: http://tracker.deltacloud.org/patch/4f61366999285c2dfbc497bdc0581c8b657d9191
---
 server/lib/cimi/collections/address_templates.rb   |  8 ++---
 server/lib/cimi/collections/addresses.rb           |  8 ++---
 server/lib/cimi/collections/cloud_entry_point.rb   |  2 +-
 server/lib/cimi/collections/credentials.rb         |  4 +--
 server/lib/cimi/collections/machine_images.rb      |  4 +--
 server/lib/cimi/collections/machine_templates.rb   | 10 +++---
 server/lib/cimi/collections/machines.rb            | 36 ++++++++--------------
 server/lib/cimi/collections/network_ports.rb       |  6 ++--
 server/lib/cimi/collections/networks.rb            |  4 +--
 server/lib/cimi/collections/resource_metadata.rb   |  4 +--
 server/lib/cimi/collections/system_templates.rb    | 10 +++---
 server/lib/cimi/collections/systems.rb             |  9 +++---
 .../lib/cimi/collections/volume_configurations.rb  |  8 ++---
 server/lib/cimi/collections/volume_images.rb       |  6 ++--
 server/lib/cimi/collections/volume_templates.rb    |  6 ++--
 server/lib/cimi/collections/volumes.rb             |  4 +--
 16 files changed, 58 insertions(+), 71 deletions(-)

diff --git a/server/lib/cimi/collections/address_templates.rb b/server/lib/cimi/collections/address_templates.rb
index 72e167d..99fe745 100644
--- a/server/lib/cimi/collections/address_templates.rb
+++ b/server/lib/cimi/collections/address_templates.rb
@@ -34,7 +34,7 @@ module CIMI::Collections
       operation :show do
         description 'Show a specific AddressTemplate'
         control do
-          address_template = CIMI::Model::AddressTemplate.find(params[:id], self)
+          address_template = AddressTemplate.find(params[:id], self)
           respond_to do |format|
             format.xml {address_template.to_xml}
             format.json {address_template.to_json}
@@ -45,8 +45,8 @@ module CIMI::Collections
       operation :create do
         description "Create new AddressTemplate"
         control do
-          addr_templ = CIMI::Model::AddressTemplateCreate.parse(request.body, request.content_type)
-          new_address_template = addr_templ.create(self)
+          addr_templ = AddressTemplateCreate.parse(self)
+          new_address_template = addr_templ.create
           headers_for_create new_address_template
           respond_to do |format|
             format.json { new_address_template.to_json }
@@ -58,7 +58,7 @@ module CIMI::Collections
       operation :destroy do
         description "Delete a specified AddressTemplate"
         control do
-          CIMI::Model::AddressTemplate.delete!(params[:id], self)
+          AddressTemplate.delete!(params[:id], self)
           no_content_with_status(200)
         end
       end
diff --git a/server/lib/cimi/collections/addresses.rb b/server/lib/cimi/collections/addresses.rb
index c34068d..682cce4 100644
--- a/server/lib/cimi/collections/addresses.rb
+++ b/server/lib/cimi/collections/addresses.rb
@@ -36,7 +36,7 @@ module CIMI::Collections
       operation :show, :with_capability => :address do
         description 'Show a specific Address'
         control do
-          address = CIMI::Model::Address.find(params[:id], self)
+          address = Address.find(params[:id], self)
           respond_to do |format|
             format.xml {address.to_xml}
             format.json {address.to_json}
@@ -47,8 +47,8 @@ module CIMI::Collections
       operation :create, :with_capability => :create_address do
         description "Create a new Address"
         control do
-          addr = CIMI::Model::AddressCreate.parse(request.body, request.content_type)
-          address = addr.create(self)
+          addr = AddressCreate.parse(self)
+          address = addr.create
           respond_to do |format|
             format.xml { address.to_xml }
             format.json { address.to_json }
@@ -60,7 +60,7 @@ module CIMI::Collections
         description "Delete a specified Address"
         param :id, :string, :required
         control do
-          CIMI::Model::Address.delete!(params[:id], self)
+          Address.delete!(params[:id], self)
           no_content_with_status(200)
         end
       end
diff --git a/server/lib/cimi/collections/cloud_entry_point.rb b/server/lib/cimi/collections/cloud_entry_point.rb
index b1240bc..37b47b2 100644
--- a/server/lib/cimi/collections/cloud_entry_point.rb
+++ b/server/lib/cimi/collections/cloud_entry_point.rb
@@ -28,7 +28,7 @@ module CIMI::Collections
           if params[:force_auth]
             halt 401 unless driver.valid_credentials?(credentials)
           end
-          entry_point = CIMI::Model::CloudEntryPoint.create(self)
+          entry_point = CIMI::Service::CloudEntryPoint.create(self)
           respond_to do |format|
             format.xml { entry_point.to_xml }
             format.json { entry_point.to_json }
diff --git a/server/lib/cimi/collections/credentials.rb b/server/lib/cimi/collections/credentials.rb
index 8d90be6..0cd44b9 100644
--- a/server/lib/cimi/collections/credentials.rb
+++ b/server/lib/cimi/collections/credentials.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
       operation :create, :with_capability => :create_key do
         description "Show specific machine admin"
         control do
-          c = CIMI::Model::CredentialCreate.parse(request.body, request.content_type)
-          new_admin = c.create(self)
+          c = CredentialCreate.parse(self)
+          new_admin = c.create
           headers_for_create new_admin
           respond_to do |format|
             format.json { new_admin.to_json }
diff --git a/server/lib/cimi/collections/machine_images.rb b/server/lib/cimi/collections/machine_images.rb
index ce9fa6a..66c74c2 100644
--- a/server/lib/cimi/collections/machine_images.rb
+++ b/server/lib/cimi/collections/machine_images.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
       operation :create, :with_capability => :create_image do
         description "Create a new machine image."
         control do
-          mi = MachineImageCreate.parse(request.body, request.content_type)
-          machine_image = mi.create(self)
+          mi = MachineImageCreate.parse(self)
+          machine_image = mi.create
           headers_for_create machine_image
           respond_to do |format|
             format.xml { machine_image.to_xml }
diff --git a/server/lib/cimi/collections/machine_templates.rb b/server/lib/cimi/collections/machine_templates.rb
index 6bdd1f2..fcdafcc 100644
--- a/server/lib/cimi/collections/machine_templates.rb
+++ b/server/lib/cimi/collections/machine_templates.rb
@@ -23,7 +23,7 @@ module CIMI::Collections
       operation :index do
         description "List all machine templates"
         control do
-          machine_templates = CIMI::Model::MachineTemplate.list(self).select_by(params['$select'])
+          machine_templates = MachineTemplate.list(self)
           respond_to do |format|
             format.xml { machine_templates.to_xml }
             format.json { machine_templates.to_json }
@@ -34,7 +34,7 @@ module CIMI::Collections
       operation :show do
         description "Show specific machine template"
         control do
-          machine_template = CIMI::Model::MachineTemplate.find(params[:id], self)
+          machine_template = MachineTemplate.find(params[:id], self)
           respond_to do |format|
             format.xml { machine_template.to_xml }
             format.json { machine_template.to_json }
@@ -45,8 +45,8 @@ module CIMI::Collections
       operation :create do
         description "Create new machine template"
         control do
-          mt = CIMI::Model::MachineTemplateCreate.parse(request.body, request.content_type)
-          new_machine_template = mt.create(self)
+          mt = MachineTemplateCreate.parse(self)
+          new_machine_template = mt.create
           headers_for_create new_machine_template
           respond_to do |format|
             format.json { new_machine_template.to_json }
@@ -58,7 +58,7 @@ module CIMI::Collections
       operation :destroy do
         description "Delete a specified machine template"
         control do
-          CIMI::Model::MachineTemplate.delete!(params[:id], self)
+          MachineTemplate.delete!(params[:id], self)
           no_content_with_status(200)
         end
       end
diff --git a/server/lib/cimi/collections/machines.rb b/server/lib/cimi/collections/machines.rb
index f3cb62a..f74b02b 100644
--- a/server/lib/cimi/collections/machines.rb
+++ b/server/lib/cimi/collections/machines.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
       operation :create, :with_capability => :create_instance do
         description "Create a new Machine entity."
         control do
-          mc = MachineCreate.parse(request.body, request.content_type)
-          new_machine = mc.create(self)
+          mc = MachineCreate.parse(self)
+          new_machine = mc.create
           headers_for_create new_machine
           respond_to do |format|
             format.json { new_machine.to_json }
@@ -69,12 +69,8 @@ module CIMI::Collections
         param :id,          :string,    :required
         control do
           machine = Machine.find(params[:id], self)
-          if current_content_type == :json
-            action = Action.from_json(request.body.read)
-          else
-            action = Action.from_xml(request.body.read)
-          end
-          machine.perform(action, self) do |operation|
+          action = Action.parse(self)
+          machine.perform(action) do |operation|
             no_content_with_status(202) if operation.success?
             # Handle errors using operation.failure?
           end
@@ -86,12 +82,8 @@ module CIMI::Collections
         param :id,          :string,    :required
         control do
           machine = Machine.find(params[:id], self)
-          if current_content_type == :json
-            action = Action.from_json(request.body.read.gsub("restart", "reboot"))
-          else
-            action = Action.from_xml(request.body.read.gsub("restart", "reboot"))
-          end
-          machine.perform(action, self) do |operation|
+          action = Action.parse(self)
+          machine.perform(action) do |operation|
             no_content_with_status(202) if operation.success?
             # Handle errors using operation.failure?
           end
@@ -103,12 +95,8 @@ module CIMI::Collections
         param :id,          :string,    :required
         control do
           machine = Machine.find(params[:id], self)
-          if current_content_type == :json
-            action = Action.from_json(request.body.read)
-          else
-            action = Action.from_xml(request.body.read)
-          end
-          machine.perform(action, self) do |operation|
+          action = Action.parse(self)
+          machine.perform(action) do |operation|
             no_content_with_status(202) if operation.success?
             # Handle errors using operation.failure?
           end
@@ -119,7 +107,7 @@ module CIMI::Collections
         description "Retrieve the Machine's DiskCollection"
         param :id,          :string,    :required
         control do
-          disks = CIMI::Model::Disk.collection_for_instance(params[:id], self)
+          disks = Disk.collection_for_instance(params[:id], self)
           respond_to do |format|
             format.json {disks.to_json}
             format.xml  {disks.to_xml}
@@ -133,7 +121,7 @@ module CIMI::Collections
         operation :index, :with_capability => :storage_volumes do
           description "Retrieve the Machine's MachineVolumeCollection"
           control do
-            volumes = CIMI::Model::MachineVolume.collection_for_instance(params[:id], self)
+            volumes = MachineVolume.collection_for_instance(params[:id], self)
             respond_to do |format|
               format.json {volumes.to_json}
               format.xml  {volumes.to_xml}
@@ -144,7 +132,7 @@ module CIMI::Collections
         operation :show, :with_capability => :storage_volumes do
           description "Retrieve a Machine's specific MachineVolume"
           control do
-            volume = CIMI::Model::MachineVolume.find(params[:id], self, params[:vol_id])
+            volume = MachineVolume.find(params[:id], self, params[:vol_id])
             respond_to do |format|
               format.json {volume.to_json}
               format.xml  {volume.to_xml}
@@ -155,7 +143,7 @@ module CIMI::Collections
         operation :destroy, :with_capability => :detach_storage_volume do
           description "Remove/detach a volume from the Machine's MachineVolumeCollection"
           control do
-            machine_volume = CIMI::Model::MachineVolume.find(params[:id], self, params[:vol_id])
+            machine_volume = MachineVolume.find(params[:id], self, params[:vol_id])
             location = machine_volume.initial_location
             machine_volumes = Machine.detach_volume(params[:vol_id], location, self)
             respond_to do |format|
diff --git a/server/lib/cimi/collections/network_ports.rb b/server/lib/cimi/collections/network_ports.rb
index 28c2df4..021ae7b 100644
--- a/server/lib/cimi/collections/network_ports.rb
+++ b/server/lib/cimi/collections/network_ports.rb
@@ -48,9 +48,9 @@ module CIMI::Collections
         description "Create a new NetworkPort"
         control do
           if current_content_type == :json
-            network_port = CIMI::Model::NetworkPort.create(request.body.read, self, :json)
+            network_port = NetworkPort.create(request.body.read, self, :json)
           else
-            network_port = CIMI::Model::NetworkPort.create(request.body.read, self, :xml)
+            network_port = NetworkPort.create(request.body.read, self, :xml)
           end
           respond_to do |format|
             format.xml { network_port.to_xml }
@@ -62,7 +62,7 @@ module CIMI::Collections
       operation :destroy, :with_capability => :delete_network_port do
         description "Delete a specified NetworkPort"
         control do
-          CIMI::Model::NetworkPort.delete!(params[:id], self)
+          NetworkPort.delete!(params[:id], self)
           no_content_with_status(200)
         end
       end
diff --git a/server/lib/cimi/collections/networks.rb b/server/lib/cimi/collections/networks.rb
index 0f32827..f3d6fc9 100644
--- a/server/lib/cimi/collections/networks.rb
+++ b/server/lib/cimi/collections/networks.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
       operation :create, :with_capability => :create_network do
         description "Create a new Network"
         control do
-          n = CIMI::Model::NetworkCreate.parse(request.body, request.content_type)
-          network = n.create(self)
+          n = NetworkCreate.parse(self)
+          network = n.create
           respond_to do |format|
             format.xml { network.to_xml}
             format.json { network.to_json }
diff --git a/server/lib/cimi/collections/resource_metadata.rb b/server/lib/cimi/collections/resource_metadata.rb
index 54de02a..f27ee33 100644
--- a/server/lib/cimi/collections/resource_metadata.rb
+++ b/server/lib/cimi/collections/resource_metadata.rb
@@ -21,7 +21,7 @@ module CIMI::Collections
       operation :index do
         description "List all resource metadata defined for this provider"
         control do
-          resource_metadata = CIMI::Model::ResourceMetadata.list(self)
+          resource_metadata = CIMI::Service::ResourceMetadata.list(self)
           respond_to do |format|
             format.xml{resource_metadata.to_xml}
             format.json{resource_metadata.to_json}
@@ -32,7 +32,7 @@ module CIMI::Collections
       operation :show do
         description "Get the resource metadata for a specific collection"
         control do
-          resource_metadata = CIMI::Model::ResourceMetadata.find(params[:id], self)
+          resource_metadata = CIMI::Service::ResourceMetadata.find(params[:id], self)
           respond_to do |format|
             format.xml{resource_metadata.to_xml}
             format.json{resource_metadata.to_json}
diff --git a/server/lib/cimi/collections/system_templates.rb b/server/lib/cimi/collections/system_templates.rb
index 7ab0d3e..fe27cd3 100644
--- a/server/lib/cimi/collections/system_templates.rb
+++ b/server/lib/cimi/collections/system_templates.rb
@@ -23,7 +23,7 @@ module CIMI::Collections
       operation :index, :with_capability => :system_templates do
         description "List all system templates"
         control do
-          system_templates = CIMI::Model::SystemTemplate.list(self).select_by(params['$select'])
+          system_templates = SystemTemplate.list(self).select_by(params['$select'])
           respond_to do |format|
             format.xml { system_templates.to_xml }
             format.json { system_templates.to_json }
@@ -34,7 +34,7 @@ module CIMI::Collections
       operation :show, :with_capability => :system_templates do
         description "Show specific system template"
         control do
-          system_template = CIMI::Model::SystemTemplate.find(params[:id], self)
+          system_template = SystemTemplate.find(params[:id], self)
           respond_to do |format|
             format.xml { system_template.to_xml }
             format.json { system_template.to_json }
@@ -46,9 +46,9 @@ module CIMI::Collections
         description "Create new system template"
         control do
           if grab_content_type(request.content_type, request.body) == :json
-            new_system_template = CIMI::Model::SystemTemplate.create_from_json(request.body.read, self)
+            new_system_template = SystemTemplate.create_from_json(request.body.read, self)
           else
-            new_system_template = CIMI::Model::SystemTemplate.create_from_xml(request.body.read, self)
+            new_system_template = SystemTemplate.create_from_xml(request.body.read, self)
           end
           headers_for_create new_system_template
           respond_to do |format|
@@ -61,7 +61,7 @@ module CIMI::Collections
       operation :destroy, :with_capability => :destroy_system_template do
         description "Delete a specified system template"
         control do
-          CIMI::Model::SystemTemplate.delete!(params[:id], self)
+          SystemTemplate.delete!(params[:id], self)
           no_content_with_status(200)
         end
       end
diff --git a/server/lib/cimi/collections/systems.rb b/server/lib/cimi/collections/systems.rb
index ded0aa6..a6adb8d 100644
--- a/server/lib/cimi/collections/systems.rb
+++ b/server/lib/cimi/collections/systems.rb
@@ -72,8 +72,7 @@ module CIMI::Collections
         param :id,          :string,    :required
         control do
           system = System.find(params[:id], self)
-          action = Action.parse(request.body,
-          request.content_type)
+          action = Action.parse(self)
           system.perform(action, self) do |operation|
             no_content_with_status(202) if operation.success?
             # Handle errors using operation.failure?
@@ -155,7 +154,7 @@ module CIMI::Collections
         operation :index, :with_capability => :storage_volumes do
           description "Retrieve the System's SystemVolumeCollection"
           control do
-            volumes = CIMI::Model::SystemVolume.collection_for_system(params[:id], self)
+            volumes = SystemVolume.collection_for_system(params[:id], self)
             respond_to do |format|
               format.json {volumes.to_json}
               format.xml  {volumes.to_xml}
@@ -166,7 +165,7 @@ module CIMI::Collections
         operation :show, :with_capability => :storage_volumes do
           description "Retrieve a System's specific SystemVolume"
           control do
-            volume = CIMI::Model::SystemVolume.find(params[:id], self, params[:vol_id])
+            volume = SystemVolume.find(params[:id], self, params[:vol_id])
             respond_to do |format|
               format.json {volume.to_json}
               format.xml  {volume.to_xml}
@@ -177,7 +176,7 @@ module CIMI::Collections
         operation :destroy, :with_capability => :detach_storage_volume do
           description "Remove/detach a volume from the System's SystemVolumeCollection"
           control do
-            system_volume = CIMI::Model::SystemVolume.find(params[:id], self, params[:vol_id])
+            system_volume = SystemVolume.find(params[:id], self, params[:vol_id])
             location = system_volume.initial_location
             system_volumes = System.detach_volume(params[:vol_id], location, self)
             respond_to do |format|
diff --git a/server/lib/cimi/collections/volume_configurations.rb b/server/lib/cimi/collections/volume_configurations.rb
index 0a33794..45a9d47 100644
--- a/server/lib/cimi/collections/volume_configurations.rb
+++ b/server/lib/cimi/collections/volume_configurations.rb
@@ -23,7 +23,7 @@ module CIMI::Collections
       operation :index, :with_capability => :storage_volumes do
         description "Get list all VolumeConfigurations"
         control do
-          volume_configuration = VolumeConfiguration.list(self).select_by(params['$select'])
+          volume_configuration = VolumeConfiguration.list(self)
           respond_to do |format|
             format.xml { volume_configuration.to_xml }
             format.json { volume_configuration.to_json }
@@ -46,9 +46,9 @@ module CIMI::Collections
         description "Create new VolumeConfiguration"
         control do
           if current_content_type == :json
-            new_config = CIMI::Model::VolumeConfiguration.create_from_json(request.body.read, self)
+            new_config = VolumeConfiguration.create_from_json(request.body.read, self)
           else
-            new_config = CIMI::Model::VolumeConfiguration.create_from_xml(request.body.read, self)
+            new_config = VolumeConfiguration.create_from_xml(request.body.read, self)
           end
           headers_for_create new_config
           respond_to do |format|
@@ -61,7 +61,7 @@ module CIMI::Collections
       operation :destroy, :with_capability => :destroy_storage_volume do
         description "Delete a specified VolumeConfiguration"
         control do
-          CIMI::Model::VolumeConfiguration.delete!(params[:id], self)
+          VolumeConfiguration.delete!(params[:id], self)
           no_content_with_status(200)
         end
       end
diff --git a/server/lib/cimi/collections/volume_images.rb b/server/lib/cimi/collections/volume_images.rb
index 1596e2d..b9970b4 100644
--- a/server/lib/cimi/collections/volume_images.rb
+++ b/server/lib/cimi/collections/volume_images.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
       operation :create, :with_capability => :create_storage_snapshot do
         description "Create a new volume image."
         control do
-          img = CIMI::Model::VolumeImageCreate.parse(request.body, request.content_type)
-          volume_image = img.create(self)
+          img = VolumeImageCreate.parse(self)
+          volume_image = img.create
           headers_for_create volume_image
           respond_to do |format|
             format.xml { volume_image.to_xml }
@@ -59,7 +59,7 @@ module CIMI::Collections
       operation :destroy, :with_capability => :destroy_storage_snapshot do
         description "Delete a specified VolumeImage"
         control do
-          CIMI::Model::VolumeImage.delete!(params[:id], self)
+          VolumeImage.delete!(params[:id], self)
           no_content_with_status 200
         end
       end
diff --git a/server/lib/cimi/collections/volume_templates.rb b/server/lib/cimi/collections/volume_templates.rb
index b844ed8..556fe96 100644
--- a/server/lib/cimi/collections/volume_templates.rb
+++ b/server/lib/cimi/collections/volume_templates.rb
@@ -46,8 +46,8 @@ module CIMI::Collections
         description "Create new VolumeTemplate"
         control do
           puts request.body
-          vol = CIMI::Model::VolumeTemplateCreate.parse(request.body, request.content_type)
-          new_template = vol.create(self)
+          vol = VolumeTemplateCreate.parse(self)
+          new_template = vol.create
           headers_for_create new_template
           respond_to do |format|
             format.json { new_template.to_json }
@@ -59,7 +59,7 @@ module CIMI::Collections
       operation :destroy, :with_capability => :destroy_storage_volume do
         description "Delete a specified VolumeTemplate"
         control do
-          CIMI::Model::VolumeTemplate.delete!(params[:id], self)
+          VolumeTemplate.delete!(params[:id], self)
           no_content_with_status(200)
         end
       end
diff --git a/server/lib/cimi/collections/volumes.rb b/server/lib/cimi/collections/volumes.rb
index 3f46591..49a58b3 100644
--- a/server/lib/cimi/collections/volumes.rb
+++ b/server/lib/cimi/collections/volumes.rb
@@ -49,8 +49,8 @@ module CIMI::Collections
       operation :create, :with_capability => :create_storage_volume do
         description "Create a new Volume."
         control do
-          vol = CIMI::Model::VolumeCreate.parse(request.body, request.content_type)
-          new_volume = vol.create(self)
+          vol = VolumeCreate.parse(self)
+          new_volume = vol.create
           headers_for_create new_volume
           respond_to do |format|
             format.json { new_volume.to_json }
-- 
1.8.1.4


[PATCH 02/14] CIMI (schema): properly generate and track embedded collection classes

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

---
 server/lib/cimi/models/schema.rb | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index b4e9377..9c27c6f 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -302,7 +302,10 @@ class CIMI::Model::Schema
         raise "Specify the class of collection entries using :class"
       end
       params[:embedded] = true
-      @collection_class = CIMI::Model::Collection.generate(opts[:class], params)
+      unless opts[:class].collection_class
+        opts[:class].collection_class = CIMI::Model::Collection.generate(opts[:class], params)
+      end
+      @collection_class = opts[:class].collection_class
     end
 
     def from_xml(xml, model)
@@ -466,7 +469,7 @@ class CIMI::Model::Schema
     end
 
     def collection(name, opts={})
-      opts[:scope] = self.class
+      opts[:scope] = self
       add_attributes!([name, opts], Collection)
     end
   end
-- 
1.8.1.4


[PATCH 04/14] CIMI: split models into model and service objects

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

The current CIMI::Model classes address two concerns:

  * serialization/deserialization of CIMI objects
  * interaction with the current driver and the DB

This patch splits these two concerns into two separate class hierarchies:
CIMI::Model for (de)serialization and CIMI::Service for interacting with
drivers/db

Besides cleaning up the code, this will make it possible to reuse
CIMI::Model classes as the basis for client code.
---
 server/lib/cimi/collections/base.rb            |   4 +-
 server/lib/cimi/helpers/cimi_helper.rb         |   2 +-
 server/lib/cimi/helpers/database_helper.rb     |   3 +-
 server/lib/cimi/models.rb                      |   9 --
 server/lib/cimi/models/base.rb                 |  74 +--------
 server/lib/cimi/models/collection.rb           |  27 +---
 server/lib/cimi/models/machine.rb              | 125 ---------------
 server/lib/cimi/service.rb                     |  28 ++++
 server/lib/cimi/service/base.rb                | 201 +++++++++++++++++++++++++
 server/lib/cimi/service/machine.rb             | 147 ++++++++++++++++++
 server/tests/cimi/collections/common.rb        |  27 ++++
 server/tests/cimi/collections/machines_test.rb |   7 +
 server/tests/cimi/db/database_helper_test.rb   |  11 +-
 13 files changed, 430 insertions(+), 235 deletions(-)
 create mode 100644 server/lib/cimi/service.rb
 create mode 100644 server/lib/cimi/service/base.rb
 create mode 100644 server/lib/cimi/service/machine.rb

diff --git a/server/lib/cimi/collections/base.rb b/server/lib/cimi/collections/base.rb
index 1e49ea3..0d1d0ee 100644
--- a/server/lib/cimi/collections/base.rb
+++ b/server/lib/cimi/collections/base.rb
@@ -13,7 +13,7 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-require_relative '../models'
+require_relative '../service'
 
 module CIMI::Collections
   class Base < Sinatra::Base
@@ -24,7 +24,7 @@ module CIMI::Collections
 
     include Sinatra::Rabbit
     include Sinatra::Rabbit::Features
-    include CIMI::Model
+    include CIMI::Service
 
     helpers Deltacloud::Helpers::Drivers
     helpers Deltacloud::Helpers::Database
diff --git a/server/lib/cimi/helpers/cimi_helper.rb b/server/lib/cimi/helpers/cimi_helper.rb
index e23d819..6d9403e 100644
--- a/server/lib/cimi/helpers/cimi_helper.rb
+++ b/server/lib/cimi/helpers/cimi_helper.rb
@@ -72,7 +72,7 @@ module CIMI
     end
 
     def deltacloud_create_method_for(cimi_entity)
-      case cimi_entity
+      case cimi_entity.to_s
         when "machine"                then "create_instance"
         when "machine_configuration"  then "create_hardware_profile"
         when "machine_image"          then "create_image"
diff --git a/server/lib/cimi/helpers/database_helper.rb b/server/lib/cimi/helpers/database_helper.rb
index 7e5f99a..b62fbbc 100644
--- a/server/lib/cimi/helpers/database_helper.rb
+++ b/server/lib/cimi/helpers/database_helper.rb
@@ -25,8 +25,7 @@ module Deltacloud
         "volume_configuration", "volume_template" ]
 
      def provides?(entity)
-       return true if DATABASE_COLLECTIONS.include? entity
-       return false
+       DATABASE_COLLECTIONS.include? entity.to_s
      end
 
       def current_provider
diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
index edfb0e3..8eeb96c 100644
--- a/server/lib/cimi/models.rb
+++ b/server/lib/cimi/models.rb
@@ -37,15 +37,6 @@ end
 
 require 'require_relative' if RUBY_VERSION < '1.9'
 
-# Database entities
-#
-require_relative './../db/provider'
-require_relative './../db/entity'
-require_relative './../db/machine_template'
-require_relative './../db/address_template'
-require_relative './../db/volume_configuration'
-require_relative './../db/volume_template'
-
 require_relative './models/schema'
 require_relative './models/resource'
 require_relative './models/collection'
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index a207bed..fc8cca8 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -15,8 +15,6 @@
 
 require 'xmlsimple'
 
-require_relative '../helpers/database_helper'
-
 # The base class for any CIMI object that we either read from a request or
 # write as a response. This class handles serializing/deserializing XML and
 # JSON into a common form.
@@ -109,86 +107,16 @@ module CIMI::Model
 
   class Base < Resource
 
-    # Extend the base model with database methods
-    extend Deltacloud::Helpers::Database
-
     # Extend the base model with the collection handling methods
     extend CIMI::Model::CollectionMethods
 
     # Include methods needed to handle the $select query parameter
     include CIMI::Helpers::SelectBaseMethods
+
     #
     # Common attributes for all resources
     #
     text :id, :name, :description, :created, :updated
     hash_map :property
-
-    def initialize(values = {})
-      super(values)
-      retrieve_entity
-    end
-
-    def []=(a, v)
-      v = super
-      retrieve_entity if a == :id
-      v
-    end
-
-    # Save the common attributes name, description, and properties to the
-    # database
-    def save
-      if @entity
-        @entity.name = name
-        @entity.description = description
-        @entity.properties = property
-        @entity.save
-      end
-      self
-    end
-
-    # Destroy the database attributes for this model
-    def destroy
-      @entity.destroy
-      self
-    end
-
-    # FIXME: Kludge around the fact that we do not have proper *Create
-    # objects that deserialize properties by themselves
-    def extract_properties!(data)
-      h = {}
-      if data['property']
-        # Data came from XML
-        h = data['property'].inject({}) do |r,v|
-          r[v['key']] = v['content']
-          r
-        end
-      elsif data['properties']
-        h = data['properties']
-      end
-      property ||= {}
-      property.merge!(h)
-    end
-
-    def ref_id(ref_url)
-      ref_url.split('/').last if ref_url
-    end
-
-    private
-
-    # Load an existing database entity for this object, or create a new one
-    def retrieve_entity
-      if self.id
-        @entity = Deltacloud::Database::Entity::retrieve(self)
-        if @entity.exists?
-          self.name = @entity.name
-          self.description = @entity.description
-          self.property ||= {}
-          self.property.merge!(@entity.properties)
-        end
-      else
-        @entity = nil
-      end
-    end
-
   end
 end
diff --git a/server/lib/cimi/models/collection.rb b/server/lib/cimi/models/collection.rb
index f36c081..cc95ab7 100644
--- a/server/lib/cimi/models/collection.rb
+++ b/server/lib/cimi/models/collection.rb
@@ -120,26 +120,15 @@ module CIMI::Model
     end
 
     # Return a collection of entities
-    def list(context)
-      entries = find(:all, context)
-      desc = "#{self.name.split("::").last} Collection for the #{context.driver.name.capitalize} driver"
-      acts_as_root_entity unless collection_class
-      id = context.send("#{collection_class.entry_name}_url")
-      ops = []
-      cimi_entity = collection_class.entry_name.to_s.singularize
-      cimi_create = "create_#{cimi_entity}_url"
-      dcloud_create = context.deltacloud_create_method_for(cimi_entity)
-      if(context.respond_to?(cimi_create) &&
-         context.driver.respond_to?(dcloud_create)) ||
-      provides?(cimi_entity)
-        url = context.send(cimi_create)
-        ops << { :rel => "add", :href => url }
+    def list(id, entries, params = {})
+      params[:id] = id
+      params[:entries] = entries
+      params[:count] = params[:entries].size
+      if params[:add_url]
+        params[:operations] ||= []
+        params[:operations] << { :rel => "add", :href => params.delete(:add_url) }
       end
-      collection_class.new(:id => id,
-                           :count => entries.size,
-                           :entries => entries,
-                           :operations => ops,
-                           :description => desc)
+      collection_class.new(params)
     end
 
     def all(context)
diff --git a/server/lib/cimi/models/machine.rb b/server/lib/cimi/models/machine.rb
index 3beb2f7..6990fb9 100644
--- a/server/lib/cimi/models/machine.rb
+++ b/server/lib/cimi/models/machine.rb
@@ -38,129 +38,4 @@ class CIMI::Model::Machine < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    instances = []
-    if id == :all
-      instances = context.driver.instances(context.credentials)
-      instances.map { |instance| from_instance(instance, context) }.compact
-    else
-      instance = context.driver.instance(context.credentials, :id => id)
-      raise CIMI::Model::NotFound unless instance
-      from_instance(instance, context)
-    end
-  end
-
-  def perform(action, context, &block)
-    begin
-      if context.driver.send(:"#{action.name}_instance", context.credentials, self.id.split("/").last)
-        block.callback :success
-      else
-        raise "Operation failed to execute on given Machine"
-      end
-    rescue => e
-      block.callback :failure, e.message
-    end
-  end
-
-  def self.delete!(id, context)
-    context.driver.destroy_instance(context.credentials, id)
-    new(:id => id).destroy
-  end
-
-  #returns the newly attach machine_volume
-  def self.attach_volume(volume, location, context)
-    context.driver.attach_storage_volume(context.credentials,
-     {:id=>volume, :instance_id=>context.params[:id], :device=>location})
-    CIMI::Model::MachineVolume.find(context.params[:id], context, volume)
-  end
-
-  #returns the machine_volume_collection for the given machine
-  def self.detach_volume(volume, location, context)
-    context.driver.detach_storage_volume(context.credentials,
-     {:id=>volume, :instance_id=>context.params[:id], :device=>location})
-    CIMI::Model::MachineVolume.collection_for_instance(context.params[:id], context)
-  end
-
-  def self.from_instance(instance, context)
-    cpu =  memory = (instance.instance_profile.id == "opaque")? "n/a" : nil
-    machine_conf = CIMI::Model::MachineConfiguration.find(instance.instance_profile.name, context)
-    machine_spec = {
-      :name => instance.name,
-      :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time.to_s).xmlschema,
-      :description => "No description set for Machine #{instance.name}",
-      :id => context.machine_url(instance.id),
-      :state => convert_instance_state(instance.state),
-      :cpu => cpu || convert_instance_cpu(instance.instance_profile, context),
-      :memory => memory || convert_instance_memory(instance.instance_profile, context),
-      :disks => { :href => context.machine_url(instance.id)+"/disks"},
-      :volumes => { :href=>context.machine_url(instance.id)+"/volumes"},
-      :operations => convert_instance_actions(instance, context)
-    }
-    if context.expand? :disks
-      machine_spec[:disks] = CIMI::Model::Disk.find(instance, machine_conf, context, :all)
-    end
-    if context.expand? :volumes
-      machine_spec[:volumes] = CIMI::Model::MachineVolume.find(instance.id, context, :all)
-    end
-    machine_spec[:realm] = instance.realm_id if instance.realm_id
-    machine_spec[:machine_image] = { :href => context.machine_image_url(instance.image_id) } if instance.image_id
-    self.new(machine_spec)
-  end
-
-  # FIXME: This will convert 'RUNNING' state to 'STARTED'
-  # which is defined in CIMI (p65)
-  #
-  def self.convert_instance_state(state)
-    case state
-      when "RUNNING" then "STARTED"
-      when "PENDING" then "CREATING" #aruba only exception... could be "STARTING" here
-      else state
-    end
-  end
-
-  def self.convert_instance_cpu(profile, context)
-    cpu_override = profile.overrides.find { |p, v| p == :cpu }
-    if cpu_override.nil?
-      CIMI::Model::MachineConfiguration.find(profile.id, context).cpu
-    else
-      cpu_override[1]
-    end
-  end
-
-  def self.convert_instance_memory(profile, context)
-    machine_conf = CIMI::Model::MachineConfiguration.find(profile.name, context)
-    memory_override = profile.overrides.find { |p, v| p == :memory }
-    memory_override.nil? ? machine_conf.memory.to_i : context.to_kibibyte(memory_override[1].to_i,"MB")
-  end
-
-  def self.convert_instance_addresses(instance)
-    (instance.public_addresses + instance.private_addresses).collect do |address|
-      {
-        :hostname => address.is_hostname? ? address : nil,
-        :mac_address => address.is_mac? ? address : nil,
-        :state => 'Active',
-        :protocol => 'IPv4',
-        :address => address.is_ipv4? ? address : nil,
-        :allocation => 'Static'
-      }
-    end
-  end
-
-  def self.convert_instance_actions(instance, context)
-    actions = instance.actions.collect do |action|
-      action = :restart if action == :reboot
-      name = action
-      name = :delete if action == :destroy # In CIMI destroy operation become delete
-      { :href => context.send(:"#{action}_machine_url", instance.id), :rel => "http://schemas.dmtf.org/cimi/1/action/#{name}" }
-    end
-    actions <<  { :href => context.send(:"machine_images_url"), :rel => "http://schemas.dmtf.org/cimi/1/action/capture" } if instance.can_create_image?
-    actions
-  end
-
-  def self.convert_storage_volumes(instance, context)
-    instance.storage_volumes ||= [] #deal with nilpointers
-    instance.storage_volumes.map{|vol| {:href=>context.volume_url(vol.keys.first),
-                                       :initial_location=>vol.values.first} }
-  end
-
 end
diff --git a/server/lib/cimi/service.rb b/server/lib/cimi/service.rb
new file mode 100644
index 0000000..5231c24
--- /dev/null
+++ b/server/lib/cimi/service.rb
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless require_relatived by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+module CIMI::Service; end
+
+require_relative './models'
+require_relative './../db/provider'
+require_relative './../db/entity'
+require_relative './../db/machine_template'
+require_relative './../db/address_template'
+require_relative './../db/volume_configuration'
+require_relative './../db/volume_template'
+
+require_relative './service/base'
+require_relative './service/machine'
diff --git a/server/lib/cimi/service/base.rb b/server/lib/cimi/service/base.rb
new file mode 100644
index 0000000..7df57f6
--- /dev/null
+++ b/server/lib/cimi/service/base.rb
@@ -0,0 +1,201 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+require 'xmlsimple'
+
+require_relative '../helpers/database_helper'
+
+# Service objects implement the server functionality of CIMI resources; in
+# particular, these objects are responsible for interacting with the
+# current driver. They use the CIMI::Model objects for (de)serialization
+module CIMI::Service
+
+  class Base
+
+    # Extend the base model with database methods
+    extend Deltacloud::Helpers::Database
+
+    attr_reader :model, :context
+
+    class << self
+      def model_class
+        CIMI::Model.const_get(name.split('::').last)
+      end
+
+      def model_name
+        name.split('::').last.underscore.to_sym
+      end
+
+      def collection_name
+        name.split('::').last.underscore.pluralize.to_sym
+      end
+
+      def inherited(subclass)
+        # Decorate all the attributes of the model class
+        schema = subclass.model_class.schema
+        schema.attribute_names.each do |name|
+          define_method(name) { self[name] }
+          define_method(:"#{name}=") { |newval| self[name] = newval }
+        end
+      end
+    end
+
+    def initialize(context, opts)
+      if opts[:values]
+        @model = model_class.new(opts[:values])
+      elsif opts[:model]
+        @model = opts[:model]
+      else
+        @model = model_class.new({})
+      end
+      @context = context
+      retrieve_entity
+    end
+
+    def model_class
+      self.class.model_class
+    end
+
+    # Decorate some model methods
+    def []=(a, v)
+      v = (@model[a] = v)
+      retrieve_entity if a == :id
+      v
+    end
+
+    def [](a)
+      @model[a]
+    end
+
+    def to_xml
+      @model.to_xml
+    end
+
+    def to_json
+      @model.to_json
+    end
+
+    def select_attributes(attr_list)
+      @model.select_attributes(attr_list)
+    end
+
+    # Lookup a reference and return the corresponding model
+    def resolve(ref)
+      self.class.resolve(ref, context)
+    end
+
+    def self.resolve(ref, ctx)
+      model = nil
+      if ref.href?
+        name = ref.class.superclass.name.split('::').last
+        service_class = CIMI::Service::const_get(name)
+        id = ref.href.split('/').last
+        model = service_class.find(id, ctx)
+      else
+        # FIXME: if ref.href? we need to overwrite
+        # attributes in model with ones from ref as long as they are present
+        model = ref
+      end
+      model
+    end
+
+    def self.list(ctx)
+      id = ctx.send("#{collection_name}_url")
+      entries = find(:all, ctx)
+      params = {}
+      params[:desc] = "#{self.name.split("::").last} Collection for the #{ctx.driver.name.capitalize} driver"
+      params[:add_url] = create_url(ctx)
+      model_class.list(id, entries, params)
+    end
+
+    def self.create_url(ctx)
+      cimi_create = "create_#{model_name}_url"
+      dcloud_create = ctx.deltacloud_create_method_for(model_name)
+      if(ctx.respond_to?(cimi_create) &&
+         ctx.driver.respond_to?(dcloud_create)) || provides?(model_name)
+        ctx.send(cimi_create)
+      end
+    end
+
+    # Save the common attributes name, description, and properties to the
+    # database
+    def save
+      if @entity
+        before_save
+        @entity.save
+      end
+      self
+    end
+
+    # Destroy the database attributes for this model
+    def destroy
+      @entity.destroy
+      self
+    end
+
+    # FIXME: Kludge around the fact that we do not have proper *Create
+    # objects that deserialize properties by themselves
+    def extract_properties!(data)
+      h = {}
+      if data['property']
+        # Data came from XML
+        h = data['property'].inject({}) do |r,v|
+          r[v['key']] = v['content']
+          r
+        end
+      elsif data['properties']
+        h = data['properties']
+      end
+      property ||= {}
+      property.merge!(h)
+    end
+
+    def ref_id(ref_url)
+      ref_url.split('/').last if ref_url
+    end
+
+    protected
+
+    def attributes_to_copy
+      [:name, :description]
+    end
+
+    def before_save
+      attributes_to_copy.each { |a| @entity[a] = @model[a] }
+      @entity.properties = @model.property
+    end
+
+    def after_retrieve
+      attributes_to_copy.each { |a| @model[a] = @entity[a] }
+      @model.property ||= {}
+      @model.property.merge!(@entity.properties)
+    end
+
+    private
+
+    # Load an existing database entity for this object, or create a new one
+    def retrieve_entity
+      if self.id
+        @entity = Deltacloud::Database::Entity::retrieve(@model)
+        if @entity.exists?
+          after_retrieve
+        end
+      else
+        @entity = nil
+      end
+    end
+
+  end
+end
diff --git a/server/lib/cimi/service/machine.rb b/server/lib/cimi/service/machine.rb
new file mode 100644
index 0000000..72e5346
--- /dev/null
+++ b/server/lib/cimi/service/machine.rb
@@ -0,0 +1,147 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::Machine < CIMI::Service::Base
+
+  def self.find(id, context)
+    instances = []
+    if id == :all
+      instances = context.driver.instances(context.credentials)
+      instances.map { |instance| from_instance(instance, context) }.compact
+    else
+      instance = context.driver.instance(context.credentials, :id => id)
+      raise CIMI::Model::NotFound unless instance
+      from_instance(instance, context)
+    end
+  end
+
+  def perform(action, &block)
+    begin
+      op = action.operation
+      op = :reboot if op == :restart
+      puts "PERFORM #{op.inspect} on #{ref_id(id)}"
+      if context.driver.send(:"#{op}_instance", context.credentials, ref_id(id))
+        block.callback :success
+      else
+        raise "Operation #{op} failed to execute on given Machine #{ref_id(id)}"
+      end
+    rescue => e
+      raise
+      block.callback :failure, e.message
+    end
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_instance(context.credentials, id)
+    new(context, :values => { :id => id }).destroy
+  end
+
+  #returns the newly attach machine_volume
+  def self.attach_volume(volume, location, context)
+    context.driver.attach_storage_volume(context.credentials,
+     {:id=>volume, :instance_id=>context.params[:id], :device=>location})
+    CIMI::Model::MachineVolume.find(context.params[:id], context, volume)
+  end
+
+  #returns the machine_volume_collection for the given machine
+  def self.detach_volume(volume, location, context)
+    context.driver.detach_storage_volume(context.credentials,
+     {:id=>volume, :instance_id=>context.params[:id], :device=>location})
+    CIMI::Model::MachineVolume.collection_for_instance(context.params[:id], context)
+  end
+
+  def self.from_instance(instance, context)
+    cpu =  memory = (instance.instance_profile.id == "opaque")? "n/a" : nil
+    machine_conf = CIMI::Model::MachineConfiguration.find(instance.instance_profile.name, context)
+    machine_spec = {
+      :name => instance.name,
+      :created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time.to_s).xmlschema,
+      :description => "No description set for Machine #{instance.name}",
+      :id => context.machine_url(instance.id),
+      :state => convert_instance_state(instance.state),
+      :cpu => cpu || convert_instance_cpu(instance.instance_profile, context),
+      :memory => memory || convert_instance_memory(instance.instance_profile, context),
+      :disks => { :href => context.machine_url(instance.id)+"/disks"},
+      :volumes => { :href=>context.machine_url(instance.id)+"/volumes"},
+      :operations => convert_instance_actions(instance, context)
+    }
+    if context.expand? :disks
+      machine_spec[:disks] = CIMI::Model::Disk.find(instance, machine_conf, context, :all)
+    end
+    if context.expand? :volumes
+      machine_spec[:volumes] = CIMI::Model::MachineVolume.find(instance.id, context, :all)
+    end
+    machine_spec[:realm] = instance.realm_id if instance.realm_id
+    machine_spec[:machine_image] = { :href => context.machine_image_url(instance.image_id) } if instance.image_id
+    self.new(context, :values => machine_spec)
+  end
+
+  # FIXME: This will convert 'RUNNING' state to 'STARTED'
+  # which is defined in CIMI (p65)
+  #
+  def self.convert_instance_state(state)
+    case state
+      when "RUNNING" then "STARTED"
+      when "PENDING" then "CREATING" #aruba only exception... could be "STARTING" here
+      else state
+    end
+  end
+
+  def self.convert_instance_cpu(profile, context)
+    cpu_override = profile.overrides.find { |p, v| p == :cpu }
+    if cpu_override.nil?
+      CIMI::Model::MachineConfiguration.find(profile.id, context).cpu
+    else
+      cpu_override[1]
+    end
+  end
+
+  def self.convert_instance_memory(profile, context)
+    machine_conf = CIMI::Model::MachineConfiguration.find(profile.name, context)
+    memory_override = profile.overrides.find { |p, v| p == :memory }
+    memory_override.nil? ? machine_conf.memory.to_i : context.to_kibibyte(memory_override[1].to_i,"MB")
+  end
+
+  def self.convert_instance_addresses(instance)
+    (instance.public_addresses + instance.private_addresses).collect do |address|
+      {
+        :hostname => address.is_hostname? ? address : nil,
+        :mac_address => address.is_mac? ? address : nil,
+        :state => 'Active',
+        :protocol => 'IPv4',
+        :address => address.is_ipv4? ? address : nil,
+        :allocation => 'Static'
+      }
+    end
+  end
+
+  def self.convert_instance_actions(instance, context)
+    actions = instance.actions.collect do |action|
+      action = :restart if action == :reboot
+      name = action
+      name = :delete if action == :destroy # In CIMI destroy operation become delete
+      { :href => context.send(:"#{action}_machine_url", instance.id), :rel => "http://schemas.dmtf.org/cimi/1/action/#{name}" }
+    end
+    actions <<  { :href => context.send(:"machine_images_url"), :rel => "http://schemas.dmtf.org/cimi/1/action/capture" } if instance.can_create_image?
+    actions
+  end
+
+  def self.convert_storage_volumes(instance, context)
+    instance.storage_volumes ||= [] #deal with nilpointers
+    instance.storage_volumes.map{|vol| {:href=>context.volume_url(vol.keys.first),
+                                       :initial_location=>vol.values.first} }
+  end
+
+end
diff --git a/server/tests/cimi/collections/common.rb b/server/tests/cimi/collections/common.rb
index 5948dde..f44f9cd 100644
--- a/server/tests/cimi/collections/common.rb
+++ b/server/tests/cimi/collections/common.rb
@@ -15,3 +15,30 @@ Deltacloud[:cimi].require!
 Deltacloud[:cimi].default_frontend!
 
 def formats; [ 'application/xml', 'application/json' ]; end
+
+def model_class
+  resource = nil
+  resp = last_response
+  ct = resp.content_type
+  if ct == "application/json"
+    json = JSON::parse(last_response.body)
+    json["resourceURI"].wont_be_nil
+    resource = json["resourceURI"].split("/").last
+  elsif ct == "application/xml"
+    xml = Nokogiri::XML(last_response.body)
+    if xml.root.name == "Collection"
+      resource = xml.root["resourceURI"].split("/").last
+    else
+      resource = xml.root.name
+    end
+  elsif resp.body.nil? || resp.body.size == 0
+    raise "Can not construct model from empty body"
+  else
+    raise "Unexpected content type #{resp.content_type}"
+  end
+  CIMI::Model::const_get(resource)
+end
+
+def model
+  model_class.parse(last_response.body, last_response.content_type)
+end
diff --git a/server/tests/cimi/collections/machines_test.rb b/server/tests/cimi/collections/machines_test.rb
index b2f7efb..5e8346e 100644
--- a/server/tests/cimi/collections/machines_test.rb
+++ b/server/tests/cimi/collections/machines_test.rb
@@ -35,6 +35,13 @@ describe CIMI::Collections::Machines do
     xml.root.name.must_equal 'Machine'
   end
 
+  it 'should have an "add" operation for the machine collection' do
+    get root_url + '/machines'
+    model.operations.wont_be_empty
+    add_ops = model.operations.select { |op| op.rel == "add" }
+    add_ops.size.must_equal 1
+  end
+
   describe "$expand" do
     def machine(*expand)
       url = '/machines/inst1'
diff --git a/server/tests/cimi/db/database_helper_test.rb b/server/tests/cimi/db/database_helper_test.rb
index b474307..43642ec 100644
--- a/server/tests/cimi/db/database_helper_test.rb
+++ b/server/tests/cimi/db/database_helper_test.rb
@@ -16,7 +16,8 @@ describe Deltacloud::Helpers::Database do
   before do
     @provider = Deltacloud::Database::Provider
     @entity = Deltacloud::Database::Entity
-    @baseModel = CIMI::Model::Base
+    @baseService = CIMI::Service::Base
+    @baseModel = @baseService.model_class
 
     @db = DatabaseHelper.new
     @prov = @provider::lookup
@@ -98,7 +99,7 @@ describe Deltacloud::Helpers::Database do
     check_entity_base_attrs new_entity, @entity, @prov
 
     base = @baseModel.new(:id => 'base1')
-    base.destroy
+    @baseService.new(nil, :model => base).destroy
     entity = @entity.retrieve(base)
     entity.wont_be_nil
     entity.exists?.must_equal false
@@ -123,10 +124,12 @@ describe Deltacloud::Helpers::Database do
   }
 }
     '
-    machine = CIMI::Model::Machine.from_json(json)
+
+    model = CIMI::Model::Machine.from_json(json)
+    machine = CIMI::Service::Machine.new(nil, :model => model)
     machine.save
 
-    m2 = CIMI::Model::Machine.new(:id => machine.id)
+    m2 = CIMI::Service::Machine.new(nil, :values => { :id => machine.id })
     m2.name.must_equal 'myDatabaseMachine'
     m2.description.must_equal 'This is a demo machine'
     m2.property.must_be_kind_of Hash
-- 
1.8.1.4


[PATCH 06/14] CIMI: Migrated MachineImage to services

Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>

Signed-off-by: Michal fojtik <mf...@redhat.com>
TrackedAt: http://tracker.deltacloud.org/patch/ac7d8b3fe7354da3cb2d29400632bfe36694556d
---
 server/lib/cimi/collections/machine_images.rb |  6 ++--
 server/lib/cimi/models/machine_image.rb       | 28 ---------------
 server/lib/cimi/service.rb                    |  1 +
 server/lib/cimi/service/machine_image.rb      | 51 +++++++++++++++++++++++++++
 4 files changed, 55 insertions(+), 31 deletions(-)
 create mode 100644 server/lib/cimi/service/machine_image.rb

diff --git a/server/lib/cimi/collections/machine_images.rb b/server/lib/cimi/collections/machine_images.rb
index ee0033c..ce9fa6a 100644
--- a/server/lib/cimi/collections/machine_images.rb
+++ b/server/lib/cimi/collections/machine_images.rb
@@ -24,7 +24,7 @@ module CIMI::Collections
       operation :index, :with_capability => :images do
         description "List all machine configurations"
         control do
-          machine_images = MachineImage.list(self).select_by(params['$select'])
+          machine_images = MachineImage.list(self)
           respond_to do |format|
             format.xml { machine_images.to_xml }
             format.json { machine_images.to_json }
@@ -46,7 +46,7 @@ module CIMI::Collections
       operation :create, :with_capability => :create_image do
         description "Create a new machine image."
         control do
-          mi = CIMI::Model::MachineImageCreate.parse(request.body, request.content_type)
+          mi = MachineImageCreate.parse(request.body, request.content_type)
           machine_image = mi.create(self)
           headers_for_create machine_image
           respond_to do |format|
@@ -59,7 +59,7 @@ module CIMI::Collections
       operation :destroy, :with_capability => :destroy_image do
         description "Delete a specified MachineImage"
         control do
-          CIMI::Model::MachineImage.delete!(params[:id], self)
+          MachineImage.delete!(params[:id], self)
           no_content_with_status 200
         end
       end
diff --git a/server/lib/cimi/models/machine_image.rb b/server/lib/cimi/models/machine_image.rb
index 74f48ef..f900dae 100644
--- a/server/lib/cimi/models/machine_image.rb
+++ b/server/lib/cimi/models/machine_image.rb
@@ -26,32 +26,4 @@ class CIMI::Model::MachineImage < CIMI::Model::Base
     scalar :rel, :href
   end
 
-  def self.find(id, context)
-    images = []
-    if id == :all
-      images = context.driver.images(context.credentials)
-      images.map { |image| from_image(image, context) }
-    else
-      image = context.driver.image(context.credentials, :id => id)
-      from_image(image, context)
-    end
-  end
-
-  def self.from_image(image, context)
-    self.new(
-      :id => context.machine_image_url(image.id),
-      :name => image.id,
-      :description => image.description,
-      :state => image.state || 'UNKNOWN',
-      :type => "IMAGE",
-      :created => image.creation_time.nil? ?
-        Time.now.xmlschema : Time.parse(image.creation_time.to_s).xmlschema
-    )
-  end
-
-  def self.delete!(image_id, context)
-    context.driver.destroy_image(context.credentials, image_id)
-    new(:id => image_id).destroy
-  end
-
 end
diff --git a/server/lib/cimi/service.rb b/server/lib/cimi/service.rb
index 5231c24..f6b933f 100644
--- a/server/lib/cimi/service.rb
+++ b/server/lib/cimi/service.rb
@@ -26,3 +26,4 @@ require_relative './../db/volume_template'
 
 require_relative './service/base'
 require_relative './service/machine'
+require_relative './service/machine_image'
diff --git a/server/lib/cimi/service/machine_image.rb b/server/lib/cimi/service/machine_image.rb
new file mode 100644
index 0000000..dad26a8
--- /dev/null
+++ b/server/lib/cimi/service/machine_image.rb
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Service::MachineImage < CIMI::Service::Base
+
+  def initialize(ctx, opts)
+    super
+  end
+
+  def self.find(id, context)
+    images = []
+    if id == :all
+      images = context.driver.images(context.credentials)
+      images.map { |image| from_image(image, context) }
+    else
+      image = context.driver.image(context.credentials, :id => id)
+      from_image(image, context)
+    end
+  end
+
+  def self.from_image(image, context)
+    self.new(context, :values => {
+      :id => context.machine_image_url(image.id),
+      :name => image.id,
+      :description => image.description,
+      :state => image.state || 'UNKNOWN',
+      :type => "IMAGE",
+      :created => image.creation_time.nil? ?
+      Time.now.xmlschema : Time.parse(image.creation_time.to_s).xmlschema
+    })
+  end
+
+  def self.delete!(image_id, context)
+    context.driver.destroy_image(context.credentials, image_id)
+    new(:id => image_id).destroy
+  end
+
+
+end
-- 
1.8.1.4


[PATCH 03/14] DB Entity: make sure we instantiate the correct subclass

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

We only ever instantiated Database::Entity, but never any of its
subclasses. We now keep a map of CIMI::Model => Database::Entity subclass
and call new on the appropriate subclass of Entity.
---
 server/lib/db/entity.rb | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/server/lib/db/entity.rb b/server/lib/db/entity.rb
index 45a7f30..7f32161 100644
--- a/server/lib/db/entity.rb
+++ b/server/lib/db/entity.rb
@@ -44,6 +44,7 @@ module Deltacloud
       end
 
       def after_initialize
+        super
         if ent_properties
           self.properties = JSON::parse(ent_properties)
         else
@@ -61,11 +62,25 @@ module Deltacloud
         entity = Provider::lookup.entities_dataset.first(h)
         unless entity
           h[:provider_id] = Provider::lookup.id
-          entity = Entity.new(h)
+          entity = @@model_entity_map[model.class].new(h)
         end
         entity
       end
 
+      def self.inherited(subclass)
+        super
+        # Build a map from CIMI::Model class to Entity subclass. This only
+        # works if the two classes have the same name in their respective
+        # modules.
+        # The map is used to determine what Entity subclass to instantiate
+        # for a given model in +retrieve+
+        @@model_entity_map ||= Hash.new(Entity)
+        n = subclass.name.split('::').last
+        if k = CIMI::Model::const_get(n)
+          @@model_entity_map[k] = subclass
+        end
+      end
+
       private
       def self.model_hash(model)
         { :be_kind => model.class.name,
-- 
1.8.1.4


[PATCH 05/14] CIMI: Apply $filter and $select in Base#list

Posted by lu...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>

No need to have ugly chained methods in collections.

Signed-off-by: Michal fojtik <mf...@redhat.com>
TrackedAt: http://tracker.deltacloud.org/patch/c2417e1f3383ae4a76e1d40d04440daed149bf95
---
 server/lib/cimi/collections/machines.rb | 2 +-
 server/lib/cimi/service/base.rb         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/server/lib/cimi/collections/machines.rb b/server/lib/cimi/collections/machines.rb
index 0337f86..f3cb62a 100644
--- a/server/lib/cimi/collections/machines.rb
+++ b/server/lib/cimi/collections/machines.rb
@@ -24,7 +24,7 @@ module CIMI::Collections
       operation :index, :with_capability => :instances do
         description "List all machines"
         control do
-          machines = Machine.list(self).select_by(params['$select']).filter_by(params['$filter'])
+          machines = Machine.list(self)
           respond_to do |format|
             format.xml { machines.to_xml }
             format.json { machines.to_json }
diff --git a/server/lib/cimi/service/base.rb b/server/lib/cimi/service/base.rb
index 7df57f6..8daa183 100644
--- a/server/lib/cimi/service/base.rb
+++ b/server/lib/cimi/service/base.rb
@@ -117,7 +117,7 @@ module CIMI::Service
       params = {}
       params[:desc] = "#{self.name.split("::").last} Collection for the #{ctx.driver.name.capitalize} driver"
       params[:add_url] = create_url(ctx)
-      model_class.list(id, entries, params)
+      model_class.list(id, entries, params).select_by(ctx.params['$select']).filter_by(ctx.params['$filter'])
     end
 
     def self.create_url(ctx)
-- 
1.8.1.4


[PATCH 11/14] * server/lib/cimi/service/machine_template.rb (delete!): fix 500 error

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

The method was simply busted. Now also allows deletion of nonexisting
templates
---
 server/lib/cimi/service/machine_template.rb | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/server/lib/cimi/service/machine_template.rb b/server/lib/cimi/service/machine_template.rb
index 4a3cd4e..837c519 100644
--- a/server/lib/cimi/service/machine_template.rb
+++ b/server/lib/cimi/service/machine_template.rb
@@ -29,7 +29,9 @@ class CIMI::Service::MachineTemplate < CIMI::Service::Base
     end
 
     def delete!(id, context)
-      current_db.machine_templates.first(:id => id).destroy
+      if mt = current_db.machine_templates_dataset.first(:id => id)
+          mt.destroy
+      end
     end
 
     def from_db(model, context)
-- 
1.8.1.4


Re: RFC: Separate CIMI (de)serialization from server functionality (rev 3)

Posted by Michal Fojtik <mf...@redhat.com>.
On 03/13, lutter@redhat.com wrote:

Applied cleanly. All tests are green. ACK this series.
I'm for pushing it and fixing small nits/etc later :-)

  -- Michal

> 
> This is the third take on splitting server-side functionality out of our
> models. As in previous attempts, CIMI::Model is now solely concerned with
> (se)serialization, whereas CIMI::Service does all the actual server-side
> functionality.
> 
> FWIW, the unit and blackbox tests all pass for me with this patch series
> ...
> 
> Also recorded as http://tracker.deltacloud.org/set/389
> 
> David

-- 
Michal Fojtik <mf...@redhat.com>
Deltacloud API, CloudForms

[PATCH 10/14] CIMI: make ResourceMetadata work with the Model/Service split

Posted by lu...@redhat.com.
From: David Lutterkort <lu...@redhat.com>

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
---
 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(-)

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
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
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
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
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] } }
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'
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
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,
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
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)
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
-- 
1.8.1.4