You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by di...@fast.au.fujitsu.com on 2013/02/08 12:44:13 UTC

[PATCH] CIMI: adding system support

From: Dies Koper <di...@fast.au.fujitsu.com>

---
 server/lib/cimi/collections/addresses.rb           |   2 +-
 server/lib/cimi/collections/machines.rb            |   2 +-
 server/lib/cimi/collections/system_templates.rb    |  72 ++++++++
 server/lib/cimi/collections/systems.rb             | 198 +++++++++++++++++++++
 server/lib/cimi/models.rb                          |  10 ++
 server/lib/cimi/models/base.rb                     |   4 +-
 server/lib/cimi/models/collection.rb               |   3 +
 server/lib/cimi/models/system.rb                   |  78 ++++++++
 server/lib/cimi/models/system_address.rb           |  90 ++++++++++
 server/lib/cimi/models/system_forwarding_group.rb  |  90 ++++++++++
 server/lib/cimi/models/system_machine.rb           |  90 ++++++++++
 server/lib/cimi/models/system_network.rb           |  90 ++++++++++
 server/lib/cimi/models/system_system.rb            |  32 ++++
 server/lib/cimi/models/system_template.rb          |  66 +++++++
 server/lib/cimi/models/system_volume.rb            |  90 ++++++++++
 .../drivers/mock/data/cimi/system/system1.json     |  12 ++
 .../mock/data/cimi/system_template/template1.json  |  27 +++
 server/lib/deltacloud/drivers/mock/mock_client.rb  |   2 +
 .../drivers/mock/mock_driver_cimi_methods.rb       |  27 +++
 19 files changed, 981 insertions(+), 4 deletions(-)
 create mode 100644 server/lib/cimi/collections/system_templates.rb
 create mode 100644 server/lib/cimi/collections/systems.rb
 create mode 100644 server/lib/cimi/models/system.rb
 create mode 100644 server/lib/cimi/models/system_address.rb
 create mode 100644 server/lib/cimi/models/system_forwarding_group.rb
 create mode 100644 server/lib/cimi/models/system_machine.rb
 create mode 100644 server/lib/cimi/models/system_network.rb
 create mode 100644 server/lib/cimi/models/system_system.rb
 create mode 100644 server/lib/cimi/models/system_template.rb
 create mode 100644 server/lib/cimi/models/system_volume.rb
 create mode 100644 server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
 create mode 100644 server/lib/deltacloud/drivers/mock/data/cimi/system_template/template1.json

diff --git a/server/lib/cimi/collections/addresses.rb b/server/lib/cimi/collections/addresses.rb
index 9ea1764..a51e658 100644
--- a/server/lib/cimi/collections/addresses.rb
+++ b/server/lib/cimi/collections/addresses.rb
@@ -20,7 +20,7 @@ module CIMI::Collections
 
     collection :addresses do
 
-      description 'An Address represents an IP address, and its associated metdata, for a particular Network.'
+      description 'An Address represents an IP address, and its associated metadata, for a particular Network.'
 
       operation :index, :with_capability => :addresses do
         description 'List all Addresses in the AddressCollection'
diff --git a/server/lib/cimi/collections/machines.rb b/server/lib/cimi/collections/machines.rb
index 5718f46..9a71bb1 100644
--- a/server/lib/cimi/collections/machines.rb
+++ b/server/lib/cimi/collections/machines.rb
@@ -85,7 +85,7 @@ module CIMI::Collections
       end
 
       action :restart, :with_capability => :reboot_instance do
-        description "Start specific machine."
+        description "Restart specific machine."
         param :id,          :string,    :required
         control do
           machine = Machine.find(params[:id], self)
diff --git a/server/lib/cimi/collections/system_templates.rb b/server/lib/cimi/collections/system_templates.rb
new file mode 100644
index 0000000..88fbe30
--- /dev/null
+++ b/server/lib/cimi/collections/system_templates.rb
@@ -0,0 +1,72 @@
+# 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.
+
+module CIMI::Collections
+  class SystemTemplates < Base
+
+    set :capability, lambda { |t| true }
+
+    collection :system_templates do
+
+      operation :index do
+        description "List all system templates"
+        control do
+          system_templates = CIMI::Model::SystemTemplate.list(self).select_by(params['$select'])
+          respond_to do |format|
+            format.xml { system_templates.to_xml }
+            format.json { system_templates.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Show specific system template"
+        control do
+          system_template = CIMI::Model::SystemTemplate.find(params[:id], self)
+          respond_to do |format|
+            format.xml { system_template.to_xml }
+            format.json { system_template.to_json }
+          end
+        end
+      end
+
+      operation :create do
+        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)
+          else
+            new_system_template = CIMI::Model::SystemTemplate.create_from_xml(request.body.read, self)
+          end
+          headers_for_create new_system_template
+          respond_to do |format|
+            format.json { new_system_template.to_json }
+            format.xml { new_system_template.to_xml }
+          end
+        end
+      end
+
+      operation :destroy do
+        description "Delete a specified system template"
+        control do
+          CIMI::Model::SystemTemplate.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/systems.rb b/server/lib/cimi/collections/systems.rb
new file mode 100644
index 0000000..250b1d2
--- /dev/null
+++ b/server/lib/cimi/collections/systems.rb
@@ -0,0 +1,198 @@
+# 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.
+
+module CIMI::Collections
+  class Systems < Base
+
+    set :capability, lambda { |m| driver.respond_to? m }
+
+    collection :systems do
+      description 'List all systems'
+
+      operation :index, :with_capability => :systems do
+        description "List all systems"
+        control do
+          systems = System.list(self).select_by(params['$select']).filter_by(params['$filter'])
+          respond_to do |format|
+            format.xml { systems.to_xml }
+            format.json { systems.to_json }
+          end
+        end
+      end
+
+      operation :show, :with_capability => :system do
+        description "Show specific system."
+        control do
+          system = System.find(params[:id], self)
+          respond_to do |format|
+            format.xml { system.to_xml }
+            format.json { system.to_json }
+          end
+        end
+      end
+
+      operation :create, :with_capability => :create_system do
+        description "Create a new System entity."
+        control do
+          if grab_content_type(request.content_type, request.body) == :json
+            new_system = System.create_from_json(request.body.read, self)
+          else
+            new_system = System.create_from_xml(request.body.read, self)
+          end
+          headers_for_create new_system
+          respond_to do |format|
+            format.json { new_system.to_json }
+            format.xml { new_system.to_xml }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_system do
+        description "Delete a specified system."
+        control do
+          System.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+      action :stop, :with_capability => :stop_system do
+        description "Stop specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :restart, :with_capability => :reboot_system do
+        description "Restart specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if  grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read.gsub("restart", "reboot"))
+          else
+            action = Action.from_xml(request.body.read.gsub("restart", "reboot"))
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :start, :with_capability => :start_system do
+        description "Start specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if  grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :pause, :with_capability => :pause_system do
+        description "Pause specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if  grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :suspend, :with_capability => :suspend_system do
+        description "Suspend specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if  grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      #use rabbit subcollections for volumes index/show:
+      collection :volumes, :with_id => :vol_id do
+
+        operation :index, :with_capability => :storage_volumes do
+          description "Retrieve the System's SystemVolumeCollection"
+          control do
+            volumes = CIMI::Model::SystemVolume.collection_for_instance(params[:id], self)
+            respond_to do |format|
+              format.json {volumes.to_json}
+              format.xml  {volumes.to_xml}
+            end
+          end
+        end
+
+        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])
+            respond_to do |format|
+              format.json {volume.to_json}
+              format.xml  {volume.to_xml}
+            end
+          end
+        end
+
+        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])
+            location = system_volume.initial_location
+            system_volumes = System.detach_volume(params[:vol_id], location, self)
+            respond_to do |format|
+              format.json{ system_volumes.to_json}
+              format.xml{ system_volumes.to_xml}
+            end
+          end
+        end
+
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
index 20c0ef1..ec1a1c9 100644
--- a/server/lib/cimi/models.rb
+++ b/server/lib/cimi/models.rb
@@ -81,3 +81,13 @@ require_relative './models/address'
 require_relative './models/address_template'
 require_relative './models/forwarding_group'
 require_relative './models/forwarding_group_template'
+require_relative './models/system_system'
+require_relative './models/system_volume'
+require_relative './models/system_machine'
+require_relative './models/system_template'
+#require_relative './models/system_credential'
+#require_relative './models/system_network_port'
+require_relative './models/system_network'
+require_relative './models/system_address'
+require_relative './models/system_forwarding_group'
+require_relative './models/system'
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index c74b8c3..2c49c75 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -63,7 +63,7 @@ require_relative '../helpers/database_helper'
 #   [struct(name, opts, &block)]
 #     A structured subobject; the block defines the schema of the
 #     subobject. The +:content+ option can be used to specify the attribute
-#     that should receive the content of hte corresponding XML element
+#     that should receive the content of the corresponding XML element
 #   [array(name, opts, &block)]
 #     An array of structured subobjects; the block defines the schema of
 #     the subobjects.
@@ -86,7 +86,7 @@ module CIMI::Model
     #
     # Common attributes for all resources
     #
-    text :id, :name, :description, :created
+    text :id, :name, :description, :created, :updated
     hash :property
   end
 
diff --git a/server/lib/cimi/models/collection.rb b/server/lib/cimi/models/collection.rb
index f36c081..17ad95b 100644
--- a/server/lib/cimi/models/collection.rb
+++ b/server/lib/cimi/models/collection.rb
@@ -121,7 +121,9 @@ module CIMI::Model
 
     # Return a collection of entities
     def list(context)
+	  puts "list(#{context}) called."
       entries = find(:all, context)
+	  puts "entries: #{entries}"
       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")
@@ -135,6 +137,7 @@ module CIMI::Model
         url = context.send(cimi_create)
         ops << { :rel => "add", :href => url }
       end
+	  puts "entries: #{entries}"
       collection_class.new(:id => id,
                            :count => entries.size,
                            :entries => entries,
diff --git a/server/lib/cimi/models/system.rb b/server/lib/cimi/models/system.rb
new file mode 100644
index 0000000..619e7a9
--- /dev/null
+++ b/server/lib/cimi/models/system.rb
@@ -0,0 +1,78 @@
+# 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::Model::System < CIMI::Model::Base
+
+  acts_as_root_entity
+
+  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
+
+  array :meters do
+    scalar :href
+  end
+
+  href :event_log
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+  puts "system#self.find called"
+    systems = []
+    if id == :all
+      systems = context.driver.systems(context.credentials, {:env=>context})
+puts "systems from driver #{systems.size}"
+    else
+      system = context.driver.system(context.credentials, {:env=>context, :id=>id})
+      raise CIMI::Model::NotFound unless system
+      system
+    end
+  end
+
+  def self.create_from_json(body, context)
+    #todo: mfojtik and lutter are refactoring this mechanism
+  end
+
+  def self.create_from_xml(body, context)
+      #todo: mfojtik and lutter are refactoring this mechanism
+  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_address.rb b/server/lib/cimi/models/system_address.rb
new file mode 100644
index 0000000..a4c88bf
--- /dev/null
+++ b/server/lib/cimi/models/system_address.rb
@@ -0,0 +1,90 @@
+# 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::Model::SystemAddress < CIMI::Model::Base
+
+  href :address
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(instance_id, context, id=:all)
+    puts "system_address#self.find called"
+    if id == :all
+      addresses = context.driver.storage_addresses(context.credentials)
+      addresses.inject([]) do |attached, vol|
+        id = context.system_url(instance_id)+"/addresses/#{vol.id}"
+        attached <<  self.new(
+          :id => id,
+          :name => vol.id,
+          :description => "SystemAddress #{vol.id} for System #{instance_id}",
+          :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+          :initial_location => vol.device,
+          :address => {:href=>context.address_url(vol.id)},
+          :operations => [{:href=>id, :rel => "delete" }]
+          ) if vol.instance_id == instance_id
+        attached
+      end
+    else
+      vol = context.driver.storage_address(context.credentials, {:id=>id})
+      id = context.system_url(instance_id)+"/addresses/#{vol.id}"
+      raise CIMI::Model::NotFound unless vol.instance_id == instance_id
+      self.new(
+        :id => id,
+        :name => vol.id,
+        :description => "SystemAddress #{vol.id} for System #{instance_id}",
+        :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+        :initial_location => vol.device,
+        :address => {:href=>context.address_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["address"].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["address"]["href"].split("/").last
+    location = json["initialLocation"]
+    [vol_id, location]
+  end
+
+
+  def self.collection_for_instance(instance_id, context)
+    system_addresses = self.find(instance_id, context)
+    addresses_url = context.url("/systems/#{instance_id}/addresses")
+    unless CIMI::Model.const_defined?('SystemAddressCollection')
+      collection_class = CIMI::Model::Collection.generate(self)
+    else
+      collection_class = CIMI::Model::SystemAddressCollection
+    end
+    collection_class.new(
+      :id => addresses_url,
+      :name => 'default',
+      :count => system_addresses.size,
+      :description => "Address collection for System #{instance_id}",
+      :entries => system_addresses,
+      :operations => [{ :href => addresses_url.singularize+"_attach", :rel => "add" }]
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/system_forwarding_group.rb b/server/lib/cimi/models/system_forwarding_group.rb
new file mode 100644
index 0000000..95c148c
--- /dev/null
+++ b/server/lib/cimi/models/system_forwarding_group.rb
@@ -0,0 +1,90 @@
+# 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::Model::SystemForwardingGroup < CIMI::Model::Base
+
+  href :forwarding_group
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(instance_id, context, id=:all)
+    puts "system_machine#self.find called"
+    if id == :all
+      forwarding_groups = context.driver.storage_forwarding_groups(context.credentials)
+      forwarding_groups.inject([]) do |attached, vol|
+        id = context.system_url(instance_id)+"/forwarding_groups/#{vol.id}"
+        attached <<  self.new(
+          :id => id,
+          :name => vol.id,
+          :description => "SystemForwardingGroup #{vol.id} for System #{instance_id}",
+          :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+          :initial_location => vol.device,
+          :forwarding_group => {:href=>context.forwarding_group_url(vol.id)},
+          :operations => [{:href=>id, :rel => "delete" }]
+          ) if vol.instance_id == instance_id
+        attached
+      end
+    else
+      vol = context.driver.storage_forwarding_group(context.credentials, {:id=>id})
+      id = context.system_url(instance_id)+"/forwarding_groups/#{vol.id}"
+      raise CIMI::Model::NotFound unless vol.instance_id == instance_id
+      self.new(
+        :id => id,
+        :name => vol.id,
+        :description => "SystemForwardingGroup #{vol.id} for System #{instance_id}",
+        :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+        :initial_location => vol.device,
+        :forwarding_group => {:href=>context.forwarding_group_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["forwarding_group"].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["forwarding_group"]["href"].split("/").last
+    location = json["initialLocation"]
+    [vol_id, location]
+  end
+
+
+  def self.collection_for_instance(instance_id, context)
+    system_forwarding_groups = self.find(instance_id, context)
+    forwarding_groups_url = context.url("/systems/#{instance_id}/forwarding_groups")
+    unless CIMI::Model.const_defined?('SystemForwardingGroupCollection')
+      collection_class = CIMI::Model::Collection.generate(self)
+    else
+      collection_class = CIMI::Model::SystemForwardingGroupCollection
+    end
+    collection_class.new(
+      :id => forwarding_groups_url,
+      :name => 'default',
+      :count => system_forwarding_groups.size,
+      :description => "ForwardingGroup collection for System #{instance_id}",
+      :entries => system_forwarding_groups,
+      :operations => [{ :href => forwarding_groups_url.singularize+"_attach", :rel => "add" }]
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/system_machine.rb b/server/lib/cimi/models/system_machine.rb
new file mode 100644
index 0000000..5c96ded
--- /dev/null
+++ b/server/lib/cimi/models/system_machine.rb
@@ -0,0 +1,90 @@
+# 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::Model::SystemMachine < CIMI::Model::Base
+
+  href :machine
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(instance_id, context, id=:all)
+    puts "system_machine#self.find called"
+    if id == :all
+      machines = context.driver.storage_machines(context.credentials)
+      machines.inject([]) do |attached, vol|
+        id = context.system_url(instance_id)+"/machines/#{vol.id}"
+        attached <<  self.new(
+          :id => id,
+          :name => vol.id,
+          :description => "SystemMachine #{vol.id} for System #{instance_id}",
+          :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+          :initial_location => vol.device,
+          :machine => {:href=>context.machine_url(vol.id)},
+          :operations => [{:href=>id, :rel => "delete" }]
+          ) if vol.instance_id == instance_id
+        attached
+      end
+    else
+      vol = context.driver.storage_machine(context.credentials, {:id=>id})
+      id = context.system_url(instance_id)+"/machines/#{vol.id}"
+      raise CIMI::Model::NotFound unless vol.instance_id == instance_id
+      self.new(
+        :id => id,
+        :name => vol.id,
+        :description => "SystemMachine #{vol.id} for System #{instance_id}",
+        :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+        :initial_location => vol.device,
+        :machine => {:href=>context.machine_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["machine"].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["machine"]["href"].split("/").last
+    location = json["initialLocation"]
+    [vol_id, location]
+  end
+
+
+  def self.collection_for_instance(instance_id, context)
+    system_machines = self.find(instance_id, context)
+    machines_url = context.url("/systems/#{instance_id}/machines")
+    unless CIMI::Model.const_defined?('SystemMachineCollection')
+      collection_class = CIMI::Model::Collection.generate(self)
+    else
+      collection_class = CIMI::Model::SystemMachineCollection
+    end
+    collection_class.new(
+      :id => machines_url,
+      :name => 'default',
+      :count => system_machines.size,
+      :description => "Machine collection for System #{instance_id}",
+      :entries => system_machines,
+      :operations => [{ :href => machines_url.singularize+"_attach", :rel => "add" }]
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/system_network.rb b/server/lib/cimi/models/system_network.rb
new file mode 100644
index 0000000..df3f831
--- /dev/null
+++ b/server/lib/cimi/models/system_network.rb
@@ -0,0 +1,90 @@
+# 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::Model::SystemNetwork < CIMI::Model::Base
+
+  href :network
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(instance_id, context, id=:all)
+    puts "SystemNetwork#self.find called"
+    if id == :all
+      networks = context.driver.storage_networks(context.credentials)
+      networks.inject([]) do |attached, vol|
+        id = context.system_url(instance_id)+"/networks/#{vol.id}"
+        attached <<  self.new(
+          :id => id,
+          :name => vol.id,
+          :description => "SystemNetwork #{vol.id} for System #{instance_id}",
+          :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+          :initial_location => vol.device,
+          :network => {:href=>context.network_url(vol.id)},
+          :operations => [{:href=>id, :rel => "delete" }]
+          ) if vol.instance_id == instance_id
+        attached
+      end
+    else
+      vol = context.driver.storage_network(context.credentials, {:id=>id})
+      id = context.system_url(instance_id)+"/networks/#{vol.id}"
+      raise CIMI::Model::NotFound unless vol.instance_id == instance_id
+      self.new(
+        :id => id,
+        :name => vol.id,
+        :description => "SystemNetwork #{vol.id} for System #{instance_id}",
+        :created => vol.created.nil? ? nil : Time.parse(vol.created).xmlschema,
+        :initial_location => vol.device,
+        :network => {:href=>context.network_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["network"].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["network"]["href"].split("/").last
+    location = json["initialLocation"]
+    [vol_id, location]
+  end
+
+
+  def self.collection_for_instance(instance_id, context)
+    system_networks = self.find(instance_id, context)
+    networks_url = context.url("/systems/#{instance_id}/networks")
+    unless CIMI::Model.const_defined?('SystemNetworkCollection')
+      collection_class = CIMI::Model::Collection.generate(self)
+    else
+      collection_class = CIMI::Model::SystemNetworkCollection
+    end
+    collection_class.new(
+      :id => networks_url,
+      :name => 'default',
+      :count => system_networks.size,
+      :description => "Network collection for System #{instance_id}",
+      :entries => system_networks,
+      :operations => [{ :href => networks_url.singularize+"_attach", :rel => "add" }]
+    )
+  end
+
+end
diff --git a/server/lib/cimi/models/system_system.rb b/server/lib/cimi/models/system_system.rb
new file mode 100644
index 0000000..41f9ae7
--- /dev/null
+++ b/server/lib/cimi/models/system_system.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::Model::SystemSystem < CIMI::Model::Base
+
+  href :system
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(instance_id, context, id=:all)
+    puts "SystemSystem#self.find called"
+  end
+
+
+  def self.collection_for_instance(instance_id, context)
+  end
+
+end
diff --git a/server/lib/cimi/models/system_template.rb b/server/lib/cimi/models/system_template.rb
new file mode 100644
index 0000000..9cfc64c
--- /dev/null
+++ b/server/lib/cimi/models/system_template.rb
@@ -0,0 +1,66 @@
+# 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::Model::SystemTemplate < CIMI::Model::Base
+
+  acts_as_root_entity
+
+  array :component_descriptors do
+    text :name, :description
+    hash :properties
+    text :type
+    scalar :component_template #or :class => CIMI::Model::Base ?
+    text :quantity
+  end
+
+  array :meter_templates do
+    scalar :href
+  end
+
+  href :event_log_template
+ 
+  array :operations do
+    scalar :rel, :href
+  end
+
+  class << self
+    def find(id, context)
+  puts "system_template#self.find called"
+      templates = []
+      if id == :all
+        templates = context.driver.system_templates(context.credentials, {:env=>context})
+puts "Templates from driver #{templates.size}"
+      else
+        template = context.driver.system_templates(context.credentials, {:env=>context, :id=>id})
+        raise CIMI::Model::NotFound unless template
+        template
+      end
+    end
+
+    def create_from_json(body, context)
+      #todo: mfojtik and lutter are refactoring this mechanism
+    end
+
+    def create_from_xml(body, context)
+      #todo: mfojtik and lutter are refactoring this mechanism
+    end
+
+    def delete!(id, context)
+      context.driver.destroy_system_template(context.credentials, id)
+    end
+
+  end
+
+end
diff --git a/server/lib/cimi/models/system_volume.rb b/server/lib/cimi/models/system_volume.rb
new file mode 100644
index 0000000..3433402
--- /dev/null
+++ b/server/lib/cimi/models/system_volume.rb
@@ -0,0 +1,90 @@
+# 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::Model::SystemVolume < CIMI::Model::Base
+
+  href :volume
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(instance_id, context, id=:all)
+    puts "system_volume#self.find called"
+    if id == :all
+      volumes = context.driver.storage_volumes(context.credentials)
+      volumes.inject([]) do |attached, vol|
+        id = context.system_url(instance_id)+"/volumes/#{vol.id}"
+        attached <<  self.new(
+          :id => id,
+          :name => vol.id,
+          :description => "SystemVolume #{vol.id} for System #{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.system_url(instance_id)+"/volumes/#{vol.id}"
+      raise CIMI::Model::NotFound unless vol.instance_id == instance_id
+      self.new(
+        :id => id,
+        :name => vol.id,
+        :description => "SystemVolume #{vol.id} for System #{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)
+    system_volumes = self.find(instance_id, context)
+    volumes_url = context.url("/systems/#{instance_id}/volumes")
+    unless CIMI::Model.const_defined?('SystemVolumeCollection')
+      collection_class = CIMI::Model::Collection.generate(self)
+    else
+      collection_class = CIMI::Model::SystemVolumeCollection
+    end
+    collection_class.new(
+      :id => volumes_url,
+      :name => 'default',
+      :count => system_volumes.size,
+      :description => "Volume collection for System #{instance_id}",
+      :entries => system_volumes,
+      :operations => [{ :href => volumes_url.singularize+"_attach", :rel => "add" }]
+    )
+  end
+
+end
diff --git a/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json b/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
new file mode 100644
index 0000000..450233d
--- /dev/null
+++ b/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
@@ -0,0 +1,12 @@
+{ "id": "http://cimi.example.org/systems/template1",
+  "name": "system1",
+  "description": "the first system",
+  "created": "Fri Feb 08 15:25:41 EET 2013",
+  "state": "STOPPED",
+  "machines": { "href": "http://cimi.example.org/systems/87654/machines"},
+  "networks": { "href": "http://cimi.example.org/systems/87654/networks"},
+  "operations": [
+    { "rel": "edit", "href": "http://cimi.example.org/networks/network1" },
+    { "rel": "delete", "href": "http://cimi.example.org/networks/network1" }
+  ]
+}
diff --git a/server/lib/deltacloud/drivers/mock/data/cimi/system_template/template1.json b/server/lib/deltacloud/drivers/mock/data/cimi/system_template/template1.json
new file mode 100644
index 0000000..0672df1
--- /dev/null
+++ b/server/lib/deltacloud/drivers/mock/data/cimi/system_template/template1.json
@@ -0,0 +1,27 @@
+{ "id": "http://cimi.example.org/system_templates/template1",
+  "name": "system template 1",
+  "description": "A mock system template",
+  "created": "Fri Feb 08 12:15:15 EET 2013",
+  "componentDescriptors": [
+    { "name": "my machine",
+      "description": "an inline mock machine template",
+      "type": "http://schemas.dmtf.org/cimi/1/Machine",
+      "machineTemplate": {
+        "name": "machine in mock system",
+        "description": "machine in ststem",
+        "machineConfig": "http://example.com/configs/m1-small",
+        "machineImage": "http://example.com/images/img1"
+      }
+    },
+    { "name": "my network",
+      "description": "a reference to an existing mock network template",
+      "type": "http://schemas.dmtf.org/cimi/1/Network",
+      "networkTemplate": {
+        "href": "http://cimi.example.org/network_templates/template1"
+      }
+    }
+  ],
+  "operations": [
+    { "rel": "edit", "href": "http://cimi.example.org/network_templates/template1" },
+    { "rel": "delete", "href": "http://cimi.example.org/network_templates/template1" }]
+}
diff --git a/server/lib/deltacloud/drivers/mock/mock_client.rb b/server/lib/deltacloud/drivers/mock/mock_client.rb
index 449b6a8..d7796a2 100644
--- a/server/lib/deltacloud/drivers/mock/mock_client.rb
+++ b/server/lib/deltacloud/drivers/mock/mock_client.rb
@@ -92,7 +92,9 @@ module Deltacloud::Drivers::Mock
     end
 
     def load_all_cimi(model_name)
+    puts "dir: #{File::join(cimi_dir(model_name), "*.json")}"
         model_files = Dir[File::join(cimi_dir(model_name), "*.json")]
+        puts "model_files: #{model_files}"
         model_files.map{|f| File.read(f)}
     end
 
diff --git a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
index 336f77b..57ea5ef 100644
--- a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
+++ b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
@@ -20,6 +20,31 @@
 module Deltacloud::Drivers::Mock
 
   class MockDriver < Deltacloud::BaseDriver
+
+    def systems(credentials, opts={})
+      check_credentials(credentials)
+      if opts[:id].nil?
+        systems = @client.load_all_cimi(:system).map{|sys| CIMI::Model::System.from_json(sys)}
+        systems.map{|sys|convert_cimi_mock_urls(:system, sys ,opts[:env])}.flatten
+      else
+        system = CIMI::Model::System.from_json(@client.load_cimi(:system, opts[:id]))
+        convert_cimi_mock_urls(:system, system, opts[:env])
+      end
+    end
+
+    def system_templates(credentials, opts={})
+      check_credentials(credentials)
+      puts "reached mock's system_templates with opts: #{opts}"
+      if opts[:id].nil?
+        system_templates = @client.load_all_cimi(:system_template).map{|sys_templ| CIMI::Model::SystemTemplate.from_json(sys_templ)}
+        puts "raw templates from files: #{system_templates}"
+        system_templates.map{|sys_templ|convert_cimi_mock_urls(:system_template, sys_templ, opts[:env])}.flatten
+      else
+        system_template = CIMI::Model::SystemTemplate.from_json(@client.load_cimi(:system_template, opts[:id]))
+        convert_cimi_mock_urls(:system_template, system_template, opts[:env])
+      end
+    end
+
     def networks(credentials, opts={})
       check_credentials(credentials)
       if opts[:id].nil?
@@ -138,6 +163,8 @@ module Deltacloud::Drivers::Mock
             end
         end
       end
+      puts "cimi_object.name = #{cimi_object.name}"
+      puts "context = #{context}"
       object_url = context.send(:"#{model_name}_url", cimi_object.name)
       cimi_object.id=object_url
       cimi_object.operations.each{|op| op.href=object_url  }
-- 
1.8.0.msysgit.0



Re: [PATCH] CIMI: adding system support

Posted by David Lutterkort <lu...@redhat.com>.
On Fri, 2013-02-08 at 19:13 +0200, marios@redhat.com wrote:
> Hi Dies:
> 
> On 08/02/13 14:10, Koper, Dies wrote:
> > This is a work in progress. At the moment I'm not making any progress
> > though:
> > 
> 
> unfortunately the patch won't apply - I think you need to rebase it and
> send again. I couldn't spot the problem from a visual inspection - but
> there's a lot of code there so hopefully I can have a better look with a
> fresh patch on Monday,

For some of these situations, the right incantation is 'git am --3way
PATCH' - that worked for me in this case.

David



Re: [PATCH] CIMI: adding system support

Posted by "marios@redhat.com" <ma...@redhat.com>.
Hi Dies:

On 08/02/13 14:10, Koper, Dies wrote:
> This is a work in progress. At the moment I'm not making any progress
> though:
> 

unfortunately the patch won't apply - I think you need to rebase it and
send again. I couldn't spot the problem from a visual inspection - but
there's a lot of code there so hopefully I can have a better look with a
fresh patch on Monday,

thanks, marios


> When listing systems or system templates, I get the following trace:
> 
>>> Listening on localhost:3001, CTRL+C to stop
> list(#<CIMI::Collections::SystemTemplates:0xc4c2690>) called.
> system_template#self.find called
> reached mock's system_templates with opts:
> env#<CIMI::Collections::SystemTemplates:0xc4c2690>
> dir: /var/tmp/deltacloud-mock-diesk/cimi/system_template/*.json
> model_files:
> /var/tmp/deltacloud-mock-diesk/cimi/system_template/template1.json
> raw templates from files: #<CIMI::Model::SystemTemplate:0xc3b28f0>
> cimi_object.name = system template 1
> context = #<CIMI::Collections::SystemTemplates:0xc4c2690>
> Templates from driver 1
> entries:
> entries:
> E, [2013-02-08T22:36:49.092238 #8748] ERROR -- 500: [NoMethodError]
> undefined method `size' for nil:NilClass
> 
> d:/sources/OSS/cloud/deltacloud/server/lib/cimi/models/collection.rb:142
> :in `list'
> d:/sources/OSS/cloud/deltacloud/server/lib/cimi/collections/system_templ
> ates.rb:26
> D:/programs/Ruby187/lib/ruby/gems/1.8/gems/sinatra-rabbit-1.1.3/lib/sina
> tra/rabbit/base.rb:396:in `instance_eval'
> D:/programs/Ruby187/lib/ruby/gems/1.8/gems/sinatra-rabbit-1.1.3/lib/sina
> tra/rabbit/base.rb:396:in `GET /system_templates'
> 
> It seems 'entries' is nil. It is supposed to be set in the find method.
> But I don't know which find method. I've put puts methods in all system
> related model's find methods but none get called.
> My model's system(_template).find does get called once at the beginning
> of the stack (see debug output above) so I'm wondering what find method
> it is trying to call anyway.
> 
> Many of the system_ subcollections are copied and pasted from existing
> classes (network.rb ?) and may still have original code.
> I believe in most cases those methods wouldn't be called anyway and can
> be removed.
> 
> Regards,
> Dies Koper
> 
> 
>> -----Original Message-----
>> From: diesk@fast.au.fujitsu.com [mailto:diesk@fast.au.fujitsu.com]
>> Sent: Friday, 8 February 2013 10:44 PM
>> To: dev@deltacloud.apache.org
>> Subject: [PATCH] CIMI: adding system support
>>
>> From: Dies Koper <di...@fast.au.fujitsu.com>
>>
>> ---
>>  server/lib/cimi/collections/addresses.rb           |   2 +-
>>  server/lib/cimi/collections/machines.rb            |   2 +-
>>  server/lib/cimi/collections/system_templates.rb    |  72 ++++++++
>>  server/lib/cimi/collections/systems.rb             | 198
>> +++++++++++++++++++++
>>  server/lib/cimi/models.rb                          |  10 ++
>>  server/lib/cimi/models/base.rb                     |   4 +-
>>  server/lib/cimi/models/collection.rb               |   3 +
>>  server/lib/cimi/models/system.rb                   |  78 ++++++++
>>  server/lib/cimi/models/system_address.rb           |  90 ++++++++++
>>  server/lib/cimi/models/system_forwarding_group.rb  |  90 ++++++++++
>>  server/lib/cimi/models/system_machine.rb           |  90 ++++++++++
>>  server/lib/cimi/models/system_network.rb           |  90 ++++++++++
>>  server/lib/cimi/models/system_system.rb            |  32 ++++
>>  server/lib/cimi/models/system_template.rb          |  66 +++++++
>>  server/lib/cimi/models/system_volume.rb            |  90 ++++++++++
>>  .../drivers/mock/data/cimi/system/system1.json     |  12 ++
>>  .../mock/data/cimi/system_template/template1.json  |  27 +++
>>  server/lib/deltacloud/drivers/mock/mock_client.rb  |   2 +
>>  .../drivers/mock/mock_driver_cimi_methods.rb       |  27 +++
>>  19 files changed, 981 insertions(+), 4 deletions(-)
>>  create mode 100644 server/lib/cimi/collections/system_templates.rb
>>  create mode 100644 server/lib/cimi/collections/systems.rb
>>  create mode 100644 server/lib/cimi/models/system.rb
>>  create mode 100644 server/lib/cimi/models/system_address.rb
>>  create mode 100644 server/lib/cimi/models/system_forwarding_group.rb
>>  create mode 100644 server/lib/cimi/models/system_machine.rb
>>  create mode 100644 server/lib/cimi/models/system_network.rb
>>  create mode 100644 server/lib/cimi/models/system_system.rb
>>  create mode 100644 server/lib/cimi/models/system_template.rb
>>  create mode 100644 server/lib/cimi/models/system_volume.rb
>>  create mode 100644
>> server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
>>  create mode 100644
>> server/lib/deltacloud/drivers/mock/data/cimi/system_template/templat
>> e1.json
>>
>> diff --git a/server/lib/cimi/collections/addresses.rb
>> b/server/lib/cimi/collections/addresses.rb
>> index 9ea1764..a51e658 100644
>> --- a/server/lib/cimi/collections/addresses.rb
>> +++ b/server/lib/cimi/collections/addresses.rb
>> @@ -20,7 +20,7 @@ module CIMI::Collections
>>
>>      collection :addresses do
>>
>> -      description 'An Address represents an IP address, and its
>> associated metdata, for a particular Network.'
>> +      description 'An Address represents an IP address, and its
>> associated metadata, for a particular Network.'
>>
>>        operation :index, :with_capability => :addresses do
>>          description 'List all Addresses in the AddressCollection'
>> diff --git a/server/lib/cimi/collections/machines.rb
>> b/server/lib/cimi/collections/machines.rb
>> index 5718f46..9a71bb1 100644
>> --- a/server/lib/cimi/collections/machines.rb
>> +++ b/server/lib/cimi/collections/machines.rb
>> @@ -85,7 +85,7 @@ module CIMI::Collections
>>        end
>>
>>        action :restart, :with_capability => :reboot_instance do
>> -        description "Start specific machine."
>> +        description "Restart specific machine."
>>          param :id,          :string,    :required
>>          control do
>>            machine = Machine.find(params[:id], self)
>> diff --git a/server/lib/cimi/collections/system_templates.rb
>> b/server/lib/cimi/collections/system_templates.rb
>> new file mode 100644
>> index 0000000..88fbe30
>> --- /dev/null
>> +++ b/server/lib/cimi/collections/system_templates.rb
>> @@ -0,0 +1,72 @@
>> +# 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.
>> +
>> +module CIMI::Collections
>> +  class SystemTemplates < Base
>> +
>> +    set :capability, lambda { |t| true }
>> +
>> +    collection :system_templates do
>> +
>> +      operation :index do
>> +        description "List all system templates"
>> +        control do
>> +          system_templates =
>> CIMI::Model::SystemTemplate.list(self).select_by(params['$select'])
>> +          respond_to do |format|
>> +            format.xml { system_templates.to_xml }
>> +            format.json { system_templates.to_json }
>> +          end
>> +        end
>> +      end
>> +
>> +      operation :show do
>> +        description "Show specific system template"
>> +        control do
>> +          system_template =
>> CIMI::Model::SystemTemplate.find(params[:id], self)
>> +          respond_to do |format|
>> +            format.xml { system_template.to_xml }
>> +            format.json { system_template.to_json }
>> +          end
>> +        end
>> +      end
>> +
>> +      operation :create do
>> +        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)
>> +          else
>> +            new_system_template =
>> CIMI::Model::SystemTemplate.create_from_xml(request.body.read, self)
>> +          end
>> +          headers_for_create new_system_template
>> +          respond_to do |format|
>> +            format.json { new_system_template.to_json }
>> +            format.xml { new_system_template.to_xml }
>> +          end
>> +        end
>> +      end
>> +
>> +      operation :destroy do
>> +        description "Delete a specified system template"
>> +        control do
>> +          CIMI::Model::SystemTemplate.delete!(params[:id], self)
>> +          no_content_with_status(200)
>> +        end
>> +      end
>> +
>> +    end
>> +
>> +  end
>> +end
>> diff --git a/server/lib/cimi/collections/systems.rb
>> b/server/lib/cimi/collections/systems.rb
>> new file mode 100644
>> index 0000000..250b1d2
>> --- /dev/null
>> +++ b/server/lib/cimi/collections/systems.rb
>> @@ -0,0 +1,198 @@
>> +# 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.
>> +
>> +module CIMI::Collections
>> +  class Systems < Base
>> +
>> +    set :capability, lambda { |m| driver.respond_to? m }
>> +
>> +    collection :systems do
>> +      description 'List all systems'
>> +
>> +      operation :index, :with_capability => :systems do
>> +        description "List all systems"
>> +        control do
>> +          systems =
>> System.list(self).select_by(params['$select']).filter_by(params['$fi
>> lter'])
>> +          respond_to do |format|
>> +            format.xml { systems.to_xml }
>> +            format.json { systems.to_json }
>> +          end
>> +        end
>> +      end
>> +
>> +      operation :show, :with_capability => :system do
>> +        description "Show specific system."
>> +        control do
>> +          system = System.find(params[:id], self)
>> +          respond_to do |format|
>> +            format.xml { system.to_xml }
>> +            format.json { system.to_json }
>> +          end
>> +        end
>> +      end
>> +
>> +      operation :create, :with_capability => :create_system do
>> +        description "Create a new System entity."
>> +        control do
>> +          if grab_content_type(request.content_type, request.body)
>> == :json
>> +            new_system = System.create_from_json(request.body.read,
>> self)
>> +          else
>> +            new_system = System.create_from_xml(request.body.read,
>> self)
>> +          end
>> +          headers_for_create new_system
>> +          respond_to do |format|
>> +            format.json { new_system.to_json }
>> +            format.xml { new_system.to_xml }
>> +          end
>> +        end
>> +      end
>> +
>> +      operation :destroy, :with_capability => :destroy_system do
>> +        description "Delete a specified system."
>> +        control do
>> +          System.delete!(params[:id], self)
>> +          no_content_with_status(200)
>> +        end
>> +      end
>> +
>> +      action :stop, :with_capability => :stop_system do
>> +        description "Stop specific system."
>> +        param :id,          :string,    :required
>> +        control do
>> +          system = System.find(params[:id], self)
>> +          if grab_content_type(request.content_type, request.body)
>> == :json
>> +            action = Action.from_json(request.body.read)
>> +          else
>> +            action = Action.from_xml(request.body.read)
>> +          end
>> +          system.perform(action, self) do |operation|
>> +            no_content_with_status(202) if operation.success?
>> +            # Handle errors using operation.failure?
>> +          end
>> +        end
>> +      end
>> +
>> +      action :restart, :with_capability => :reboot_system do
>> +        description "Restart specific system."
>> +        param :id,          :string,    :required
>> +        control do
>> +          system = System.find(params[:id], self)
>> +          if  grab_content_type(request.content_type, request.body)
>> == :json
>> +            action =
>> Action.from_json(request.body.read.gsub("restart", "reboot"))
>> +          else
>> +            action =
>> Action.from_xml(request.body.read.gsub("restart", "reboot"))
>> +          end
>> +          system.perform(action, self) do |operation|
>> +            no_content_with_status(202) if operation.success?
>> +            # Handle errors using operation.failure?
>> +          end
>> +        end
>> +      end
>> +
>> +      action :start, :with_capability => :start_system do
>> +        description "Start specific system."
>> +        param :id,          :string,    :required
>> +        control do
>> +          system = System.find(params[:id], self)
>> +          if  grab_content_type(request.content_type, request.body)
>> == :json
>> +            action = Action.from_json(request.body.read)
>> +          else
>> +            action = Action.from_xml(request.body.read)
>> +          end
>> +          system.perform(action, self) do |operation|
>> +            no_content_with_status(202) if operation.success?
>> +            # Handle errors using operation.failure?
>> +          end
>> +        end
>> +      end
>> +
>> +      action :pause, :with_capability => :pause_system do
>> +        description "Pause specific system."
>> +        param :id,          :string,    :required
>> +        control do
>> +          system = System.find(params[:id], self)
>> +          if  grab_content_type(request.content_type, request.body)
>> == :json
>> +            action = Action.from_json(request.body.read)
>> +          else
>> +            action = Action.from_xml(request.body.read)
>> +          end
>> +          system.perform(action, self) do |operation|
>> +            no_content_with_status(202) if operation.success?
>> +            # Handle errors using operation.failure?
>> +          end
>> +        end
>> +      end
>> +
>> +      action :suspend, :with_capability => :suspend_system do
>> +        description "Suspend specific system."
>> +        param :id,          :string,    :required
>> +        control do
>> +          system = System.find(params[:id], self)
>> +          if  grab_content_type(request.content_type, request.body)
>> == :json
>> +            action = Action.from_json(request.body.read)
>> +          else
>> +            action = Action.from_xml(request.body.read)
>> +          end
>> +          system.perform(action, self) do |operation|
>> +            no_content_with_status(202) if operation.success?
>> +            # Handle errors using operation.failure?
>> +          end
>> +        end
>> +      end
>> +
>> +      #use rabbit subcollections for volumes index/show:
>> +      collection :volumes, :with_id => :vol_id do
>> +
>> +        operation :index, :with_capability => :storage_volumes do
>> +          description "Retrieve the System's SystemVolumeCollection"
>> +          control do
>> +            volumes =
>> CIMI::Model::SystemVolume.collection_for_instance(params[:id], self)
>> +            respond_to do |format|
>> +              format.json {volumes.to_json}
>> +              format.xml  {volumes.to_xml}
>> +            end
>> +          end
>> +        end
>> +
>> +        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])
>> +            respond_to do |format|
>> +              format.json {volume.to_json}
>> +              format.xml  {volume.to_xml}
>> +            end
>> +          end
>> +        end
>> +
>> +        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])
>> +            location = system_volume.initial_location
>> +            system_volumes = System.detach_volume(params[:vol_id],
>> location, self)
>> +            respond_to do |format|
>> +              format.json{ system_volumes.to_json}
>> +              format.xml{ system_volumes.to_xml}
>> +            end
>> +          end
>> +        end
>> +
>> +      end
>> +
>> +    end
>> +
>> +  end
>> +end
>> diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
>> index 20c0ef1..ec1a1c9 100644
>> --- a/server/lib/cimi/models.rb
>> +++ b/server/lib/cimi/models.rb
>> @@ -81,3 +81,13 @@ require_relative './models/address'
>>  require_relative './models/address_template'
>>  require_relative './models/forwarding_group'
>>  require_relative './models/forwarding_group_template'
>> +require_relative './models/system_system'
>> +require_relative './models/system_volume'
>> +require_relative './models/system_machine'
>> +require_relative './models/system_template'
>> +#require_relative './models/system_credential'
>> +#require_relative './models/system_network_port'
>> +require_relative './models/system_network'
>> +require_relative './models/system_address'
>> +require_relative './models/system_forwarding_group'
>> +require_relative './models/system'
>> diff --git a/server/lib/cimi/models/base.rb
>> b/server/lib/cimi/models/base.rb
>> index c74b8c3..2c49c75 100644
>> --- a/server/lib/cimi/models/base.rb
>> +++ b/server/lib/cimi/models/base.rb
>> @@ -63,7 +63,7 @@ require_relative '../helpers/database_helper'
>>  #   [struct(name, opts, &block)]
>>  #     A structured subobject; the block defines the schema of the
>>  #     subobject. The +:content+ option can be used to specify the
>> attribute
>> -#     that should receive the content of hte corresponding XML
> element
>> +#     that should receive the content of the corresponding XML
> element
>>  #   [array(name, opts, &block)]
>>  #     An array of structured subobjects; the block defines the schema
>> of
>>  #     the subobjects.
>> @@ -86,7 +86,7 @@ module CIMI::Model
>>      #
>>      # Common attributes for all resources
>>      #
>> -    text :id, :name, :description, :created
>> +    text :id, :name, :description, :created, :updated
>>      hash :property
>>    end
>>
>> diff --git a/server/lib/cimi/models/collection.rb
>> b/server/lib/cimi/models/collection.rb
>> index f36c081..17ad95b 100644
>> --- a/server/lib/cimi/models/collection.rb
>> +++ b/server/lib/cimi/models/collection.rb
>> @@ -121,7 +121,9 @@ module CIMI::Model
>>
>>      # Return a collection of entities
>>      def list(context)
>> +	  puts "list(#{context}) called."
>>        entries = find(:all, context)
>> +	  puts "entries: #{entries}"
>>        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")
>> @@ -135,6 +137,7 @@ module CIMI::Model
>>          url = context.send(cimi_create)
>>          ops << { :rel => "add", :href => url }
>>        end
>> +	  puts "entries: #{entries}"
>>        collection_class.new(:id => id,
>>                             :count => entries.size,
>>                             :entries => entries,
>> diff --git a/server/lib/cimi/models/system.rb
>> b/server/lib/cimi/models/system.rb
>> new file mode 100644
>> index 0000000..619e7a9
>> --- /dev/null
>> +++ b/server/lib/cimi/models/system.rb
>> @@ -0,0 +1,78 @@
>> +# 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::Model::System < CIMI::Model::Base
>> +
>> +  acts_as_root_entity
>> +
>> +  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
>> +
>> +  array :meters do
>> +    scalar :href
>> +  end
>> +
>> +  href :event_log
>> +
>> +  array :operations do
>> +    scalar :rel, :href
>> +  end
>> +
>> +  def self.find(id, context)
>> +  puts "system#self.find called"
>> +    systems = []
>> +    if id == :all
>> +      systems = context.driver.systems(context.credentials,
>> {:env=>context})
>> +puts "systems from driver #{systems.size}"
>> +    else
>> +      system = context.driver.system(context.credentials,
>> {:env=>context, :id=>id})
>> +      raise CIMI::Model::NotFound unless system
>> +      system
>> +    end
>> +  end
>> +
>> +  def self.create_from_json(body, context)
>> +    #todo: mfojtik and lutter are refactoring this mechanism
>> +  end
>> +
>> +  def self.create_from_xml(body, context)
>> +      #todo: mfojtik and lutter are refactoring this mechanism
>> +  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_address.rb
>> b/server/lib/cimi/models/system_address.rb
>> new file mode 100644
>> index 0000000..a4c88bf
>> --- /dev/null
>> +++ b/server/lib/cimi/models/system_address.rb
>> @@ -0,0 +1,90 @@
>> +# 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::Model::SystemAddress < CIMI::Model::Base
>> +
>> +  href :address
>> +
>> +  array :operations do
>> +    scalar :rel, :href
>> +  end
>> +
>> +  def self.find(instance_id, context, id=:all)
>> +    puts "system_address#self.find called"
>> +    if id == :all
>> +      addresses =
>> context.driver.storage_addresses(context.credentials)
>> +      addresses.inject([]) do |attached, vol|
>> +        id = context.system_url(instance_id)+"/addresses/#{vol.id}"
>> +        attached <<  self.new(
>> +          :id => id,
>> +          :name => vol.id,
>> +          :description => "SystemAddress #{vol.id} for System
>> #{instance_id}",
>> +          :created => vol.created.nil? ? nil :
>> Time.parse(vol.created).xmlschema,
>> +          :initial_location => vol.device,
>> +          :address => {:href=>context.address_url(vol.id)},
>> +          :operations => [{:href=>id, :rel => "delete" }]
>> +          ) if vol.instance_id == instance_id
>> +        attached
>> +      end
>> +    else
>> +      vol = context.driver.storage_address(context.credentials,
>> {:id=>id})
>> +      id = context.system_url(instance_id)+"/addresses/#{vol.id}"
>> +      raise CIMI::Model::NotFound unless vol.instance_id ==
>> instance_id
>> +      self.new(
>> +        :id => id,
>> +        :name => vol.id,
>> +        :description => "SystemAddress #{vol.id} for System
>> #{instance_id}",
>> +        :created => vol.created.nil? ? nil :
>> Time.parse(vol.created).xmlschema,
>> +        :initial_location => vol.device,
>> +        :address => {:href=>context.address_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["address"].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["address"]["href"].split("/").last
>> +    location = json["initialLocation"]
>> +    [vol_id, location]
>> +  end
>> +
>> +
>> +  def self.collection_for_instance(instance_id, context)
>> +    system_addresses = self.find(instance_id, context)
>> +    addresses_url = context.url("/systems/#{instance_id}/addresses")
>> +    unless CIMI::Model.const_defined?('SystemAddressCollection')
>> +      collection_class = CIMI::Model::Collection.generate(self)
>> +    else
>> +      collection_class = CIMI::Model::SystemAddressCollection
>> +    end
>> +    collection_class.new(
>> +      :id => addresses_url,
>> +      :name => 'default',
>> +      :count => system_addresses.size,
>> +      :description => "Address collection for System #{instance_id}",
>> +      :entries => system_addresses,
>> +      :operations => [{ :href =>
>> addresses_url.singularize+"_attach", :rel => "add" }]
>> +    )
>> +  end
>> +
>> +end
>> diff --git a/server/lib/cimi/models/system_forwarding_group.rb
>> b/server/lib/cimi/models/system_forwarding_group.rb
>> new file mode 100644
>> index 0000000..95c148c
>> --- /dev/null
>> +++ b/server/lib/cimi/models/system_forwarding_group.rb
>> @@ -0,0 +1,90 @@
>> +# 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::Model::SystemForwardingGroup < CIMI::Model::Base
>> +
>> +  href :forwarding_group
>> +
>> +  array :operations do
>> +    scalar :rel, :href
>> +  end
>> +
>> +  def self.find(instance_id, context, id=:all)
>> +    puts "system_machine#self.find called"
>> +    if id == :all
>> +      forwarding_groups =
>> context.driver.storage_forwarding_groups(context.credentials)
>> +      forwarding_groups.inject([]) do |attached, vol|
>> +        id =
>> context.system_url(instance_id)+"/forwarding_groups/#{vol.id}"
>> +        attached <<  self.new(
>> +          :id => id,
>> +          :name => vol.id,
>> +          :description => "SystemForwardingGroup #{vol.id} for System
>> #{instance_id}",
>> +          :created => vol.created.nil? ? nil :
>> Time.parse(vol.created).xmlschema,
>> +          :initial_location => vol.device,
>> +          :forwarding_group =>
>> {:href=>context.forwarding_group_url(vol.id)},
>> +          :operations => [{:href=>id, :rel => "delete" }]
>> +          ) if vol.instance_id == instance_id
>> +        attached
>> +      end
>> +    else
>> +      vol =
>> context.driver.storage_forwarding_group(context.credentials,
>> {:id=>id})
>> +      id =
>> context.system_url(instance_id)+"/forwarding_groups/#{vol.id}"
>> +      raise CIMI::Model::NotFound unless vol.instance_id ==
>> instance_id
>> +      self.new(
>> +        :id => id,
>> +        :name => vol.id,
>> +        :description => "SystemForwardingGroup #{vol.id} for System
>> #{instance_id}",
>> +        :created => vol.created.nil? ? nil :
>> Time.parse(vol.created).xmlschema,
>> +        :initial_location => vol.device,
>> +        :forwarding_group =>
>> {:href=>context.forwarding_group_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["forwarding_group"].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["forwarding_group"]["href"].split("/").last
>> +    location = json["initialLocation"]
>> +    [vol_id, location]
>> +  end
>> +
>> +
>> +  def self.collection_for_instance(instance_id, context)
>> +    system_forwarding_groups = self.find(instance_id, context)
>> +    forwarding_groups_url =
>> context.url("/systems/#{instance_id}/forwarding_groups")
>> +    unless
>> CIMI::Model.const_defined?('SystemForwardingGroupCollection')
>> +      collection_class = CIMI::Model::Collection.generate(self)
>> +    else
>> +      collection_class =
>> CIMI::Model::SystemForwardingGroupCollection
>> +    end
>> +    collection_class.new(
>> +      :id => forwarding_groups_url,
>> +      :name => 'default',
>> +      :count => system_forwarding_groups.size,
>> +      :description => "ForwardingGroup collection for System
>> #{instance_id}",
>> +      :entries => system_forwarding_groups,
>> +      :operations => [{ :href =>
>> forwarding_groups_url.singularize+"_attach", :rel => "add" }]
>> +    )
>> +  end
>> +
>> +end
>> diff --git a/server/lib/cimi/models/system_machine.rb
>> b/server/lib/cimi/models/system_machine.rb
>> new file mode 100644
>> index 0000000..5c96ded
>> --- /dev/null
>> +++ b/server/lib/cimi/models/system_machine.rb
>> @@ -0,0 +1,90 @@
>> +# 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::Model::SystemMachine < CIMI::Model::Base
>> +
>> +  href :machine
>> +
>> +  array :operations do
>> +    scalar :rel, :href
>> +  end
>> +
>> +  def self.find(instance_id, context, id=:all)
>> +    puts "system_machine#self.find called"
>> +    if id == :all
>> +      machines =
>> context.driver.storage_machines(context.credentials)
>> +      machines.inject([]) do |attached, vol|
>> +        id = context.system_url(instance_id)+"/machines/#{vol.id}"
>> +        attached <<  self.new(
>> +          :id => id,
>> +          :name => vol.id,
>> +          :description => "SystemMachine #{vol.id} for System
>> #{instance_id}",
>> +          :created => vol.created.nil? ? nil :
>> Time.parse(vol.created).xmlschema,
>> +          :initial_location => vol.device,
>> +          :machine => {:href=>context.machine_url(vol.id)},
>> +          :operations => [{:href=>id, :rel => "delete" }]
>> +          ) if vol.instance_id == instance_id
>> +        attached
>> +      end
>> +    else
>> +      vol = context.driver.storage_machine(context.credentials,
>> {:id=>id})
>> +      id = context.system_url(instance_id)+"/machines/#{vol.id}"
>> +      raise CIMI::Model::NotFound unless vol.instance_id ==
>> instance_id
>> +      self.new(
>> +        :id => id,
>> +        :name => vol.id,
>> +        :description => "SystemMachine #{vol.id} for System
>> #{instance_id}",
>> +        :created => vol.created.nil? ? nil :
>> Time.parse(vol.created).xmlschema,
>> +        :initial_location => vol.device,
>> +        :machine => {:href=>context.machine_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["machine"].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["machine"]["href"].split("/").last
>> +    location = json["initialLocation"]
>> +    [vol_id, location]
>> +  end
>> +
>> +
>> +  def self.collection_for_instance(instance_id, context)
>> +    system_machines = self.find(instance_id, context)
>> +    machines_url = context.url("/systems/#{instance_id}/machines")
>> +    unless CIMI::Model.const_defined?('SystemMachineCollection')
>> +      collection_class = CIMI::Model::Collection.generate(self)
>> +    else
>> +      collection_class = CIMI::Model::SystemMachineCollection
>> +    end
>> +    collection_class.new(
>> +      :id => machines_url,
>> +      :name => 'default',
>> +      :count => system_machines.size,
>> +      :description => "Machine collection for System #{instance_id}",
>> +      :entries => system_machines,
>> +      :operations => [{ :href =>
>> machines_url.singularize+"_attach", :rel => "add" }]
>> +    )
>> +  end
>> +
>> +end
>> diff --git a/server/lib/cimi/models/system_network.rb
>> b/server/lib/cimi/models/system_network.rb
>> new file mode 100644
>> index 0000000..df3f831
>> --- /dev/null
>> +++ b/server/lib/cimi/models/system_network.rb
>> @@ -0,0 +1,90 @@
>> +# 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::Model::SystemNetwork < CIMI::Model::Base
>> +
>> +  href :network
>> +
>> +  array :operations do
>> +    scalar :rel, :href
>> +  end
>> +
>> +  def self.find(instance_id, context, id=:all)
>> +    puts "SystemNetwork#self.find called"
>> +    if id == :all
>> +      networks =
>> context.driver.storage_networks(context.credentials)
>> +      networks.inject([]) do |attached, vol|
>> +        id = context.system_url(instance_id)+"/networks/#{vol.id}"
>> +        attached <<  self.new(
>> +          :id => id,
>> +          :name => vol.id,
>> +          :description => "SystemNetwork #{vol.id} for System
>> #{instance_id}",
>> +          :created => vol.created.nil? ? nil :
>> Time.parse(vol.created).xmlschema,
>> +          :initial_location => vol.device,
>> +          :network => {:href=>context.network_url(vol.id)},
>> +          :operations => [{:href=>id, :rel => "delete" }]
>> +          ) if vol.instance_id == instance_id
>> +        attached
>> +      end
>> +    else
>> +      vol = context.driver.storage_network(context.credentials,
>> {:id=>id})
>> +      id = context.system_url(instance_id)+"/networks/#{vol.id}"
>> +      raise CIMI::Model::NotFound unless vol.instance_id ==
>> instance_id
>> +      self.new(
>> +        :id => id,
>> +        :name => vol.id,
>> +        :description => "SystemNetwork #{vol.id} for System
>> #{instance_id}",
>> +        :created => vol.created.nil? ? nil :
>> Time.parse(vol.created).xmlschema,
>> +        :initial_location => vol.device,
>> +        :network => {:href=>context.network_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["network"].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["network"]["href"].split("/").last
>> +    location = json["initialLocation"]
>> +    [vol_id, location]
>> +  end
>> +
>> +
>> +  def self.collection_for_instance(instance_id, context)
>> +    system_networks = self.find(instance_id, context)
>> +    networks_url = context.url("/systems/#{instance_id}/networks")
>> +    unless CIMI::Model.const_defined?('SystemNetworkCollection')
>> +      collection_class = CIMI::Model::Collection.generate(self)
>> +    else
>> +      collection_class = CIMI::Model::SystemNetworkCollection
>> +    end
>> +    collection_class.new(
>> +      :id => networks_url,
>> +      :name => 'default',
>> +      :count => system_networks.size,
>> +      :description => "Network collection for System #{instance_id}",
>> +      :entries => system_networks,
>> +      :operations => [{ :href =>
>> networks_url.singularize+"_attach", :rel => "add" }]
>> +    )
>> +  end
>> +
>> +end
>> diff --git a/server/lib/cimi/models/system_system.rb
>> b/server/lib/cimi/models/system_system.rb
>> new file mode 100644
>> index 0000000..41f9ae7
>> --- /dev/null
>> +++ b/server/lib/cimi/models/system_system.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::Model::SystemSystem < CIMI::Model::Base
>> +
>> +  href :system
>> +
>> +  array :operations do
>> +    scalar :rel, :href
>> +  end
>> +
>> +  def self.find(instance_id, context, id=:all)
>> +    puts "SystemSystem#self.find called"
>> +  end
>> +
>> +
>> +  def self.collection_for_instance(instance_id, context)
>> +  end
>> +
>> +end
>> diff --git a/server/lib/cimi/models/system_template.rb
>> b/server/lib/cimi/models/system_template.rb
>> new file mode 100644
>> index 0000000..9cfc64c
>> --- /dev/null
>> +++ b/server/lib/cimi/models/system_template.rb
>> @@ -0,0 +1,66 @@
>> +# 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::Model::SystemTemplate < CIMI::Model::Base
>> +
>> +  acts_as_root_entity
>> +
>> +  array :component_descriptors do
>> +    text :name, :description
>> +    hash :properties
>> +    text :type
>> +    scalar :component_template #or :class => CIMI::Model::Base ?
>> +    text :quantity
>> +  end
>> +
>> +  array :meter_templates do
>> +    scalar :href
>> +  end
>> +
>> +  href :event_log_template
>> +
>> +  array :operations do
>> +    scalar :rel, :href
>> +  end
>> +
>> +  class << self
>> +    def find(id, context)
>> +  puts "system_template#self.find called"
>> +      templates = []
>> +      if id == :all
>> +        templates =
>> context.driver.system_templates(context.credentials, {:env=>context})
>> +puts "Templates from driver #{templates.size}"
>> +      else
>> +        template =
>> context.driver.system_templates(context.credentials,
>> {:env=>context, :id=>id})
>> +        raise CIMI::Model::NotFound unless template
>> +        template
>> +      end
>> +    end
>> +
>> +    def create_from_json(body, context)
>> +      #todo: mfojtik and lutter are refactoring this mechanism
>> +    end
>> +
>> +    def create_from_xml(body, context)
>> +      #todo: mfojtik and lutter are refactoring this mechanism
>> +    end
>> +
>> +    def delete!(id, context)
>> +      context.driver.destroy_system_template(context.credentials,
>> id)
>> +    end
>> +
>> +  end
>> +
>> +end
>> diff --git a/server/lib/cimi/models/system_volume.rb
>> b/server/lib/cimi/models/system_volume.rb
>> new file mode 100644
>> index 0000000..3433402
>> --- /dev/null
>> +++ b/server/lib/cimi/models/system_volume.rb
>> @@ -0,0 +1,90 @@
>> +# 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::Model::SystemVolume < CIMI::Model::Base
>> +
>> +  href :volume
>> +
>> +  array :operations do
>> +    scalar :rel, :href
>> +  end
>> +
>> +  def self.find(instance_id, context, id=:all)
>> +    puts "system_volume#self.find called"
>> +    if id == :all
>> +      volumes = context.driver.storage_volumes(context.credentials)
>> +      volumes.inject([]) do |attached, vol|
>> +        id = context.system_url(instance_id)+"/volumes/#{vol.id}"
>> +        attached <<  self.new(
>> +          :id => id,
>> +          :name => vol.id,
>> +          :description => "SystemVolume #{vol.id} for System
>> #{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.system_url(instance_id)+"/volumes/#{vol.id}"
>> +      raise CIMI::Model::NotFound unless vol.instance_id ==
>> instance_id
>> +      self.new(
>> +        :id => id,
>> +        :name => vol.id,
>> +        :description => "SystemVolume #{vol.id} for System
>> #{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)
>> +    system_volumes = self.find(instance_id, context)
>> +    volumes_url = context.url("/systems/#{instance_id}/volumes")
>> +    unless CIMI::Model.const_defined?('SystemVolumeCollection')
>> +      collection_class = CIMI::Model::Collection.generate(self)
>> +    else
>> +      collection_class = CIMI::Model::SystemVolumeCollection
>> +    end
>> +    collection_class.new(
>> +      :id => volumes_url,
>> +      :name => 'default',
>> +      :count => system_volumes.size,
>> +      :description => "Volume collection for System #{instance_id}",
>> +      :entries => system_volumes,
>> +      :operations => [{ :href =>
>> volumes_url.singularize+"_attach", :rel => "add" }]
>> +    )
>> +  end
>> +
>> +end
>> diff --git
>> a/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
>> b/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
>> new file mode 100644
>> index 0000000..450233d
>> --- /dev/null
>> +++
>> b/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
>> @@ -0,0 +1,12 @@
>> +{ "id": "http://cimi.example.org/systems/template1",
>> +  "name": "system1",
>> +  "description": "the first system",
>> +  "created": "Fri Feb 08 15:25:41 EET 2013",
>> +  "state": "STOPPED",
>> +  "machines": { "href":
>> "http://cimi.example.org/systems/87654/machines"},
>> +  "networks": { "href":
>> "http://cimi.example.org/systems/87654/networks"},
>> +  "operations": [
>> +    { "rel": "edit", "href":
>> "http://cimi.example.org/networks/network1" },
>> +    { "rel": "delete", "href":
>> "http://cimi.example.org/networks/network1" }
>> +  ]
>> +}
>> diff --git
>> a/server/lib/deltacloud/drivers/mock/data/cimi/system_template/templ
>> ate1.json
>> b/server/lib/deltacloud/drivers/mock/data/cimi/system_template/templ
>> ate1.json
>> new file mode 100644
>> index 0000000..0672df1
>> --- /dev/null
>> +++
>> b/server/lib/deltacloud/drivers/mock/data/cimi/system_template/templ
>> ate1.json
>> @@ -0,0 +1,27 @@
>> +{ "id": "http://cimi.example.org/system_templates/template1",
>> +  "name": "system template 1",
>> +  "description": "A mock system template",
>> +  "created": "Fri Feb 08 12:15:15 EET 2013",
>> +  "componentDescriptors": [
>> +    { "name": "my machine",
>> +      "description": "an inline mock machine template",
>> +      "type": "http://schemas.dmtf.org/cimi/1/Machine",
>> +      "machineTemplate": {
>> +        "name": "machine in mock system",
>> +        "description": "machine in ststem",
>> +        "machineConfig": "http://example.com/configs/m1-small",
>> +        "machineImage": "http://example.com/images/img1"
>> +      }
>> +    },
>> +    { "name": "my network",
>> +      "description": "a reference to an existing mock network
> template",
>> +      "type": "http://schemas.dmtf.org/cimi/1/Network",
>> +      "networkTemplate": {
>> +        "href":
>> "http://cimi.example.org/network_templates/template1"
>> +      }
>> +    }
>> +  ],
>> +  "operations": [
>> +    { "rel": "edit", "href":
>> "http://cimi.example.org/network_templates/template1" },
>> +    { "rel": "delete", "href":
>> "http://cimi.example.org/network_templates/template1" }]
>> +}
>> diff --git a/server/lib/deltacloud/drivers/mock/mock_client.rb
>> b/server/lib/deltacloud/drivers/mock/mock_client.rb
>> index 449b6a8..d7796a2 100644
>> --- a/server/lib/deltacloud/drivers/mock/mock_client.rb
>> +++ b/server/lib/deltacloud/drivers/mock/mock_client.rb
>> @@ -92,7 +92,9 @@ module Deltacloud::Drivers::Mock
>>      end
>>
>>      def load_all_cimi(model_name)
>> +    puts "dir: #{File::join(cimi_dir(model_name), "*.json")}"
>>          model_files = Dir[File::join(cimi_dir(model_name), "*.json")]
>> +        puts "model_files: #{model_files}"
>>          model_files.map{|f| File.read(f)}
>>      end
>>
>> diff --git
>> a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
>> b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
>> index 336f77b..57ea5ef 100644
>> --- a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
>> +++ b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
>> @@ -20,6 +20,31 @@
>>  module Deltacloud::Drivers::Mock
>>
>>    class MockDriver < Deltacloud::BaseDriver
>> +
>> +    def systems(credentials, opts={})
>> +      check_credentials(credentials)
>> +      if opts[:id].nil?
>> +        systems = @client.load_all_cimi(:system).map{|sys|
>> CIMI::Model::System.from_json(sys)}
>> +        systems.map{|sys|convert_cimi_mock_urls(:system,
>> sys ,opts[:env])}.flatten
>> +      else
>> +        system =
>> CIMI::Model::System.from_json(@client.load_cimi(:system, opts[:id]))
>> +        convert_cimi_mock_urls(:system, system, opts[:env])
>> +      end
>> +    end
>> +
>> +    def system_templates(credentials, opts={})
>> +      check_credentials(credentials)
>> +      puts "reached mock's system_templates with opts: #{opts}"
>> +      if opts[:id].nil?
>> +        system_templates =
>> @client.load_all_cimi(:system_template).map{|sys_templ|
>> CIMI::Model::SystemTemplate.from_json(sys_templ)}
>> +        puts "raw templates from files: #{system_templates}"
>> +
>> system_templates.map{|sys_templ|convert_cimi_mock_urls(:system_templ
>> ate, sys_templ, opts[:env])}.flatten
>> +      else
>> +        system_template =
>> CIMI::Model::SystemTemplate.from_json(@client.load_cimi(:system_temp
>> late, opts[:id]))
>> +        convert_cimi_mock_urls(:system_template, system_template,
>> opts[:env])
>> +      end
>> +    end
>> +
>>      def networks(credentials, opts={})
>>        check_credentials(credentials)
>>        if opts[:id].nil?
>> @@ -138,6 +163,8 @@ module Deltacloud::Drivers::Mock
>>              end
>>          end
>>        end
>> +      puts "cimi_object.name = #{cimi_object.name}"
>> +      puts "context = #{context}"
>>        object_url = context.send(:"#{model_name}_url",
>> cimi_object.name)
>>        cimi_object.id=object_url
>>        cimi_object.operations.each{|op| op.href=object_url  }
>> --
>> 1.8.0.msysgit.0
>>
>>
> 
> 


RE: [PATCH] CIMI: adding system support

Posted by "Koper, Dies" <di...@fast.au.fujitsu.com>.
This is a work in progress. At the moment I'm not making any progress
though:

When listing systems or system templates, I get the following trace:

>> Listening on localhost:3001, CTRL+C to stop
list(#<CIMI::Collections::SystemTemplates:0xc4c2690>) called.
system_template#self.find called
reached mock's system_templates with opts:
env#<CIMI::Collections::SystemTemplates:0xc4c2690>
dir: /var/tmp/deltacloud-mock-diesk/cimi/system_template/*.json
model_files:
/var/tmp/deltacloud-mock-diesk/cimi/system_template/template1.json
raw templates from files: #<CIMI::Model::SystemTemplate:0xc3b28f0>
cimi_object.name = system template 1
context = #<CIMI::Collections::SystemTemplates:0xc4c2690>
Templates from driver 1
entries:
entries:
E, [2013-02-08T22:36:49.092238 #8748] ERROR -- 500: [NoMethodError]
undefined method `size' for nil:NilClass

d:/sources/OSS/cloud/deltacloud/server/lib/cimi/models/collection.rb:142
:in `list'
d:/sources/OSS/cloud/deltacloud/server/lib/cimi/collections/system_templ
ates.rb:26
D:/programs/Ruby187/lib/ruby/gems/1.8/gems/sinatra-rabbit-1.1.3/lib/sina
tra/rabbit/base.rb:396:in `instance_eval'
D:/programs/Ruby187/lib/ruby/gems/1.8/gems/sinatra-rabbit-1.1.3/lib/sina
tra/rabbit/base.rb:396:in `GET /system_templates'

It seems 'entries' is nil. It is supposed to be set in the find method.
But I don't know which find method. I've put puts methods in all system
related model's find methods but none get called.
My model's system(_template).find does get called once at the beginning
of the stack (see debug output above) so I'm wondering what find method
it is trying to call anyway.

Many of the system_ subcollections are copied and pasted from existing
classes (network.rb ?) and may still have original code.
I believe in most cases those methods wouldn't be called anyway and can
be removed.

Regards,
Dies Koper


> -----Original Message-----
> From: diesk@fast.au.fujitsu.com [mailto:diesk@fast.au.fujitsu.com]
> Sent: Friday, 8 February 2013 10:44 PM
> To: dev@deltacloud.apache.org
> Subject: [PATCH] CIMI: adding system support
> 
> From: Dies Koper <di...@fast.au.fujitsu.com>
> 
> ---
>  server/lib/cimi/collections/addresses.rb           |   2 +-
>  server/lib/cimi/collections/machines.rb            |   2 +-
>  server/lib/cimi/collections/system_templates.rb    |  72 ++++++++
>  server/lib/cimi/collections/systems.rb             | 198
> +++++++++++++++++++++
>  server/lib/cimi/models.rb                          |  10 ++
>  server/lib/cimi/models/base.rb                     |   4 +-
>  server/lib/cimi/models/collection.rb               |   3 +
>  server/lib/cimi/models/system.rb                   |  78 ++++++++
>  server/lib/cimi/models/system_address.rb           |  90 ++++++++++
>  server/lib/cimi/models/system_forwarding_group.rb  |  90 ++++++++++
>  server/lib/cimi/models/system_machine.rb           |  90 ++++++++++
>  server/lib/cimi/models/system_network.rb           |  90 ++++++++++
>  server/lib/cimi/models/system_system.rb            |  32 ++++
>  server/lib/cimi/models/system_template.rb          |  66 +++++++
>  server/lib/cimi/models/system_volume.rb            |  90 ++++++++++
>  .../drivers/mock/data/cimi/system/system1.json     |  12 ++
>  .../mock/data/cimi/system_template/template1.json  |  27 +++
>  server/lib/deltacloud/drivers/mock/mock_client.rb  |   2 +
>  .../drivers/mock/mock_driver_cimi_methods.rb       |  27 +++
>  19 files changed, 981 insertions(+), 4 deletions(-)
>  create mode 100644 server/lib/cimi/collections/system_templates.rb
>  create mode 100644 server/lib/cimi/collections/systems.rb
>  create mode 100644 server/lib/cimi/models/system.rb
>  create mode 100644 server/lib/cimi/models/system_address.rb
>  create mode 100644 server/lib/cimi/models/system_forwarding_group.rb
>  create mode 100644 server/lib/cimi/models/system_machine.rb
>  create mode 100644 server/lib/cimi/models/system_network.rb
>  create mode 100644 server/lib/cimi/models/system_system.rb
>  create mode 100644 server/lib/cimi/models/system_template.rb
>  create mode 100644 server/lib/cimi/models/system_volume.rb
>  create mode 100644
> server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
>  create mode 100644
> server/lib/deltacloud/drivers/mock/data/cimi/system_template/templat
> e1.json
> 
> diff --git a/server/lib/cimi/collections/addresses.rb
> b/server/lib/cimi/collections/addresses.rb
> index 9ea1764..a51e658 100644
> --- a/server/lib/cimi/collections/addresses.rb
> +++ b/server/lib/cimi/collections/addresses.rb
> @@ -20,7 +20,7 @@ module CIMI::Collections
> 
>      collection :addresses do
> 
> -      description 'An Address represents an IP address, and its
> associated metdata, for a particular Network.'
> +      description 'An Address represents an IP address, and its
> associated metadata, for a particular Network.'
> 
>        operation :index, :with_capability => :addresses do
>          description 'List all Addresses in the AddressCollection'
> diff --git a/server/lib/cimi/collections/machines.rb
> b/server/lib/cimi/collections/machines.rb
> index 5718f46..9a71bb1 100644
> --- a/server/lib/cimi/collections/machines.rb
> +++ b/server/lib/cimi/collections/machines.rb
> @@ -85,7 +85,7 @@ module CIMI::Collections
>        end
> 
>        action :restart, :with_capability => :reboot_instance do
> -        description "Start specific machine."
> +        description "Restart specific machine."
>          param :id,          :string,    :required
>          control do
>            machine = Machine.find(params[:id], self)
> diff --git a/server/lib/cimi/collections/system_templates.rb
> b/server/lib/cimi/collections/system_templates.rb
> new file mode 100644
> index 0000000..88fbe30
> --- /dev/null
> +++ b/server/lib/cimi/collections/system_templates.rb
> @@ -0,0 +1,72 @@
> +# 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.
> +
> +module CIMI::Collections
> +  class SystemTemplates < Base
> +
> +    set :capability, lambda { |t| true }
> +
> +    collection :system_templates do
> +
> +      operation :index do
> +        description "List all system templates"
> +        control do
> +          system_templates =
> CIMI::Model::SystemTemplate.list(self).select_by(params['$select'])
> +          respond_to do |format|
> +            format.xml { system_templates.to_xml }
> +            format.json { system_templates.to_json }
> +          end
> +        end
> +      end
> +
> +      operation :show do
> +        description "Show specific system template"
> +        control do
> +          system_template =
> CIMI::Model::SystemTemplate.find(params[:id], self)
> +          respond_to do |format|
> +            format.xml { system_template.to_xml }
> +            format.json { system_template.to_json }
> +          end
> +        end
> +      end
> +
> +      operation :create do
> +        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)
> +          else
> +            new_system_template =
> CIMI::Model::SystemTemplate.create_from_xml(request.body.read, self)
> +          end
> +          headers_for_create new_system_template
> +          respond_to do |format|
> +            format.json { new_system_template.to_json }
> +            format.xml { new_system_template.to_xml }
> +          end
> +        end
> +      end
> +
> +      operation :destroy do
> +        description "Delete a specified system template"
> +        control do
> +          CIMI::Model::SystemTemplate.delete!(params[:id], self)
> +          no_content_with_status(200)
> +        end
> +      end
> +
> +    end
> +
> +  end
> +end
> diff --git a/server/lib/cimi/collections/systems.rb
> b/server/lib/cimi/collections/systems.rb
> new file mode 100644
> index 0000000..250b1d2
> --- /dev/null
> +++ b/server/lib/cimi/collections/systems.rb
> @@ -0,0 +1,198 @@
> +# 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.
> +
> +module CIMI::Collections
> +  class Systems < Base
> +
> +    set :capability, lambda { |m| driver.respond_to? m }
> +
> +    collection :systems do
> +      description 'List all systems'
> +
> +      operation :index, :with_capability => :systems do
> +        description "List all systems"
> +        control do
> +          systems =
> System.list(self).select_by(params['$select']).filter_by(params['$fi
> lter'])
> +          respond_to do |format|
> +            format.xml { systems.to_xml }
> +            format.json { systems.to_json }
> +          end
> +        end
> +      end
> +
> +      operation :show, :with_capability => :system do
> +        description "Show specific system."
> +        control do
> +          system = System.find(params[:id], self)
> +          respond_to do |format|
> +            format.xml { system.to_xml }
> +            format.json { system.to_json }
> +          end
> +        end
> +      end
> +
> +      operation :create, :with_capability => :create_system do
> +        description "Create a new System entity."
> +        control do
> +          if grab_content_type(request.content_type, request.body)
> == :json
> +            new_system = System.create_from_json(request.body.read,
> self)
> +          else
> +            new_system = System.create_from_xml(request.body.read,
> self)
> +          end
> +          headers_for_create new_system
> +          respond_to do |format|
> +            format.json { new_system.to_json }
> +            format.xml { new_system.to_xml }
> +          end
> +        end
> +      end
> +
> +      operation :destroy, :with_capability => :destroy_system do
> +        description "Delete a specified system."
> +        control do
> +          System.delete!(params[:id], self)
> +          no_content_with_status(200)
> +        end
> +      end
> +
> +      action :stop, :with_capability => :stop_system do
> +        description "Stop specific system."
> +        param :id,          :string,    :required
> +        control do
> +          system = System.find(params[:id], self)
> +          if grab_content_type(request.content_type, request.body)
> == :json
> +            action = Action.from_json(request.body.read)
> +          else
> +            action = Action.from_xml(request.body.read)
> +          end
> +          system.perform(action, self) do |operation|
> +            no_content_with_status(202) if operation.success?
> +            # Handle errors using operation.failure?
> +          end
> +        end
> +      end
> +
> +      action :restart, :with_capability => :reboot_system do
> +        description "Restart specific system."
> +        param :id,          :string,    :required
> +        control do
> +          system = System.find(params[:id], self)
> +          if  grab_content_type(request.content_type, request.body)
> == :json
> +            action =
> Action.from_json(request.body.read.gsub("restart", "reboot"))
> +          else
> +            action =
> Action.from_xml(request.body.read.gsub("restart", "reboot"))
> +          end
> +          system.perform(action, self) do |operation|
> +            no_content_with_status(202) if operation.success?
> +            # Handle errors using operation.failure?
> +          end
> +        end
> +      end
> +
> +      action :start, :with_capability => :start_system do
> +        description "Start specific system."
> +        param :id,          :string,    :required
> +        control do
> +          system = System.find(params[:id], self)
> +          if  grab_content_type(request.content_type, request.body)
> == :json
> +            action = Action.from_json(request.body.read)
> +          else
> +            action = Action.from_xml(request.body.read)
> +          end
> +          system.perform(action, self) do |operation|
> +            no_content_with_status(202) if operation.success?
> +            # Handle errors using operation.failure?
> +          end
> +        end
> +      end
> +
> +      action :pause, :with_capability => :pause_system do
> +        description "Pause specific system."
> +        param :id,          :string,    :required
> +        control do
> +          system = System.find(params[:id], self)
> +          if  grab_content_type(request.content_type, request.body)
> == :json
> +            action = Action.from_json(request.body.read)
> +          else
> +            action = Action.from_xml(request.body.read)
> +          end
> +          system.perform(action, self) do |operation|
> +            no_content_with_status(202) if operation.success?
> +            # Handle errors using operation.failure?
> +          end
> +        end
> +      end
> +
> +      action :suspend, :with_capability => :suspend_system do
> +        description "Suspend specific system."
> +        param :id,          :string,    :required
> +        control do
> +          system = System.find(params[:id], self)
> +          if  grab_content_type(request.content_type, request.body)
> == :json
> +            action = Action.from_json(request.body.read)
> +          else
> +            action = Action.from_xml(request.body.read)
> +          end
> +          system.perform(action, self) do |operation|
> +            no_content_with_status(202) if operation.success?
> +            # Handle errors using operation.failure?
> +          end
> +        end
> +      end
> +
> +      #use rabbit subcollections for volumes index/show:
> +      collection :volumes, :with_id => :vol_id do
> +
> +        operation :index, :with_capability => :storage_volumes do
> +          description "Retrieve the System's SystemVolumeCollection"
> +          control do
> +            volumes =
> CIMI::Model::SystemVolume.collection_for_instance(params[:id], self)
> +            respond_to do |format|
> +              format.json {volumes.to_json}
> +              format.xml  {volumes.to_xml}
> +            end
> +          end
> +        end
> +
> +        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])
> +            respond_to do |format|
> +              format.json {volume.to_json}
> +              format.xml  {volume.to_xml}
> +            end
> +          end
> +        end
> +
> +        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])
> +            location = system_volume.initial_location
> +            system_volumes = System.detach_volume(params[:vol_id],
> location, self)
> +            respond_to do |format|
> +              format.json{ system_volumes.to_json}
> +              format.xml{ system_volumes.to_xml}
> +            end
> +          end
> +        end
> +
> +      end
> +
> +    end
> +
> +  end
> +end
> diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
> index 20c0ef1..ec1a1c9 100644
> --- a/server/lib/cimi/models.rb
> +++ b/server/lib/cimi/models.rb
> @@ -81,3 +81,13 @@ require_relative './models/address'
>  require_relative './models/address_template'
>  require_relative './models/forwarding_group'
>  require_relative './models/forwarding_group_template'
> +require_relative './models/system_system'
> +require_relative './models/system_volume'
> +require_relative './models/system_machine'
> +require_relative './models/system_template'
> +#require_relative './models/system_credential'
> +#require_relative './models/system_network_port'
> +require_relative './models/system_network'
> +require_relative './models/system_address'
> +require_relative './models/system_forwarding_group'
> +require_relative './models/system'
> diff --git a/server/lib/cimi/models/base.rb
> b/server/lib/cimi/models/base.rb
> index c74b8c3..2c49c75 100644
> --- a/server/lib/cimi/models/base.rb
> +++ b/server/lib/cimi/models/base.rb
> @@ -63,7 +63,7 @@ require_relative '../helpers/database_helper'
>  #   [struct(name, opts, &block)]
>  #     A structured subobject; the block defines the schema of the
>  #     subobject. The +:content+ option can be used to specify the
> attribute
> -#     that should receive the content of hte corresponding XML
element
> +#     that should receive the content of the corresponding XML
element
>  #   [array(name, opts, &block)]
>  #     An array of structured subobjects; the block defines the schema
> of
>  #     the subobjects.
> @@ -86,7 +86,7 @@ module CIMI::Model
>      #
>      # Common attributes for all resources
>      #
> -    text :id, :name, :description, :created
> +    text :id, :name, :description, :created, :updated
>      hash :property
>    end
> 
> diff --git a/server/lib/cimi/models/collection.rb
> b/server/lib/cimi/models/collection.rb
> index f36c081..17ad95b 100644
> --- a/server/lib/cimi/models/collection.rb
> +++ b/server/lib/cimi/models/collection.rb
> @@ -121,7 +121,9 @@ module CIMI::Model
> 
>      # Return a collection of entities
>      def list(context)
> +	  puts "list(#{context}) called."
>        entries = find(:all, context)
> +	  puts "entries: #{entries}"
>        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")
> @@ -135,6 +137,7 @@ module CIMI::Model
>          url = context.send(cimi_create)
>          ops << { :rel => "add", :href => url }
>        end
> +	  puts "entries: #{entries}"
>        collection_class.new(:id => id,
>                             :count => entries.size,
>                             :entries => entries,
> diff --git a/server/lib/cimi/models/system.rb
> b/server/lib/cimi/models/system.rb
> new file mode 100644
> index 0000000..619e7a9
> --- /dev/null
> +++ b/server/lib/cimi/models/system.rb
> @@ -0,0 +1,78 @@
> +# 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::Model::System < CIMI::Model::Base
> +
> +  acts_as_root_entity
> +
> +  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
> +
> +  array :meters do
> +    scalar :href
> +  end
> +
> +  href :event_log
> +
> +  array :operations do
> +    scalar :rel, :href
> +  end
> +
> +  def self.find(id, context)
> +  puts "system#self.find called"
> +    systems = []
> +    if id == :all
> +      systems = context.driver.systems(context.credentials,
> {:env=>context})
> +puts "systems from driver #{systems.size}"
> +    else
> +      system = context.driver.system(context.credentials,
> {:env=>context, :id=>id})
> +      raise CIMI::Model::NotFound unless system
> +      system
> +    end
> +  end
> +
> +  def self.create_from_json(body, context)
> +    #todo: mfojtik and lutter are refactoring this mechanism
> +  end
> +
> +  def self.create_from_xml(body, context)
> +      #todo: mfojtik and lutter are refactoring this mechanism
> +  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_address.rb
> b/server/lib/cimi/models/system_address.rb
> new file mode 100644
> index 0000000..a4c88bf
> --- /dev/null
> +++ b/server/lib/cimi/models/system_address.rb
> @@ -0,0 +1,90 @@
> +# 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::Model::SystemAddress < CIMI::Model::Base
> +
> +  href :address
> +
> +  array :operations do
> +    scalar :rel, :href
> +  end
> +
> +  def self.find(instance_id, context, id=:all)
> +    puts "system_address#self.find called"
> +    if id == :all
> +      addresses =
> context.driver.storage_addresses(context.credentials)
> +      addresses.inject([]) do |attached, vol|
> +        id = context.system_url(instance_id)+"/addresses/#{vol.id}"
> +        attached <<  self.new(
> +          :id => id,
> +          :name => vol.id,
> +          :description => "SystemAddress #{vol.id} for System
> #{instance_id}",
> +          :created => vol.created.nil? ? nil :
> Time.parse(vol.created).xmlschema,
> +          :initial_location => vol.device,
> +          :address => {:href=>context.address_url(vol.id)},
> +          :operations => [{:href=>id, :rel => "delete" }]
> +          ) if vol.instance_id == instance_id
> +        attached
> +      end
> +    else
> +      vol = context.driver.storage_address(context.credentials,
> {:id=>id})
> +      id = context.system_url(instance_id)+"/addresses/#{vol.id}"
> +      raise CIMI::Model::NotFound unless vol.instance_id ==
> instance_id
> +      self.new(
> +        :id => id,
> +        :name => vol.id,
> +        :description => "SystemAddress #{vol.id} for System
> #{instance_id}",
> +        :created => vol.created.nil? ? nil :
> Time.parse(vol.created).xmlschema,
> +        :initial_location => vol.device,
> +        :address => {:href=>context.address_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["address"].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["address"]["href"].split("/").last
> +    location = json["initialLocation"]
> +    [vol_id, location]
> +  end
> +
> +
> +  def self.collection_for_instance(instance_id, context)
> +    system_addresses = self.find(instance_id, context)
> +    addresses_url = context.url("/systems/#{instance_id}/addresses")
> +    unless CIMI::Model.const_defined?('SystemAddressCollection')
> +      collection_class = CIMI::Model::Collection.generate(self)
> +    else
> +      collection_class = CIMI::Model::SystemAddressCollection
> +    end
> +    collection_class.new(
> +      :id => addresses_url,
> +      :name => 'default',
> +      :count => system_addresses.size,
> +      :description => "Address collection for System #{instance_id}",
> +      :entries => system_addresses,
> +      :operations => [{ :href =>
> addresses_url.singularize+"_attach", :rel => "add" }]
> +    )
> +  end
> +
> +end
> diff --git a/server/lib/cimi/models/system_forwarding_group.rb
> b/server/lib/cimi/models/system_forwarding_group.rb
> new file mode 100644
> index 0000000..95c148c
> --- /dev/null
> +++ b/server/lib/cimi/models/system_forwarding_group.rb
> @@ -0,0 +1,90 @@
> +# 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::Model::SystemForwardingGroup < CIMI::Model::Base
> +
> +  href :forwarding_group
> +
> +  array :operations do
> +    scalar :rel, :href
> +  end
> +
> +  def self.find(instance_id, context, id=:all)
> +    puts "system_machine#self.find called"
> +    if id == :all
> +      forwarding_groups =
> context.driver.storage_forwarding_groups(context.credentials)
> +      forwarding_groups.inject([]) do |attached, vol|
> +        id =
> context.system_url(instance_id)+"/forwarding_groups/#{vol.id}"
> +        attached <<  self.new(
> +          :id => id,
> +          :name => vol.id,
> +          :description => "SystemForwardingGroup #{vol.id} for System
> #{instance_id}",
> +          :created => vol.created.nil? ? nil :
> Time.parse(vol.created).xmlschema,
> +          :initial_location => vol.device,
> +          :forwarding_group =>
> {:href=>context.forwarding_group_url(vol.id)},
> +          :operations => [{:href=>id, :rel => "delete" }]
> +          ) if vol.instance_id == instance_id
> +        attached
> +      end
> +    else
> +      vol =
> context.driver.storage_forwarding_group(context.credentials,
> {:id=>id})
> +      id =
> context.system_url(instance_id)+"/forwarding_groups/#{vol.id}"
> +      raise CIMI::Model::NotFound unless vol.instance_id ==
> instance_id
> +      self.new(
> +        :id => id,
> +        :name => vol.id,
> +        :description => "SystemForwardingGroup #{vol.id} for System
> #{instance_id}",
> +        :created => vol.created.nil? ? nil :
> Time.parse(vol.created).xmlschema,
> +        :initial_location => vol.device,
> +        :forwarding_group =>
> {:href=>context.forwarding_group_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["forwarding_group"].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["forwarding_group"]["href"].split("/").last
> +    location = json["initialLocation"]
> +    [vol_id, location]
> +  end
> +
> +
> +  def self.collection_for_instance(instance_id, context)
> +    system_forwarding_groups = self.find(instance_id, context)
> +    forwarding_groups_url =
> context.url("/systems/#{instance_id}/forwarding_groups")
> +    unless
> CIMI::Model.const_defined?('SystemForwardingGroupCollection')
> +      collection_class = CIMI::Model::Collection.generate(self)
> +    else
> +      collection_class =
> CIMI::Model::SystemForwardingGroupCollection
> +    end
> +    collection_class.new(
> +      :id => forwarding_groups_url,
> +      :name => 'default',
> +      :count => system_forwarding_groups.size,
> +      :description => "ForwardingGroup collection for System
> #{instance_id}",
> +      :entries => system_forwarding_groups,
> +      :operations => [{ :href =>
> forwarding_groups_url.singularize+"_attach", :rel => "add" }]
> +    )
> +  end
> +
> +end
> diff --git a/server/lib/cimi/models/system_machine.rb
> b/server/lib/cimi/models/system_machine.rb
> new file mode 100644
> index 0000000..5c96ded
> --- /dev/null
> +++ b/server/lib/cimi/models/system_machine.rb
> @@ -0,0 +1,90 @@
> +# 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::Model::SystemMachine < CIMI::Model::Base
> +
> +  href :machine
> +
> +  array :operations do
> +    scalar :rel, :href
> +  end
> +
> +  def self.find(instance_id, context, id=:all)
> +    puts "system_machine#self.find called"
> +    if id == :all
> +      machines =
> context.driver.storage_machines(context.credentials)
> +      machines.inject([]) do |attached, vol|
> +        id = context.system_url(instance_id)+"/machines/#{vol.id}"
> +        attached <<  self.new(
> +          :id => id,
> +          :name => vol.id,
> +          :description => "SystemMachine #{vol.id} for System
> #{instance_id}",
> +          :created => vol.created.nil? ? nil :
> Time.parse(vol.created).xmlschema,
> +          :initial_location => vol.device,
> +          :machine => {:href=>context.machine_url(vol.id)},
> +          :operations => [{:href=>id, :rel => "delete" }]
> +          ) if vol.instance_id == instance_id
> +        attached
> +      end
> +    else
> +      vol = context.driver.storage_machine(context.credentials,
> {:id=>id})
> +      id = context.system_url(instance_id)+"/machines/#{vol.id}"
> +      raise CIMI::Model::NotFound unless vol.instance_id ==
> instance_id
> +      self.new(
> +        :id => id,
> +        :name => vol.id,
> +        :description => "SystemMachine #{vol.id} for System
> #{instance_id}",
> +        :created => vol.created.nil? ? nil :
> Time.parse(vol.created).xmlschema,
> +        :initial_location => vol.device,
> +        :machine => {:href=>context.machine_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["machine"].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["machine"]["href"].split("/").last
> +    location = json["initialLocation"]
> +    [vol_id, location]
> +  end
> +
> +
> +  def self.collection_for_instance(instance_id, context)
> +    system_machines = self.find(instance_id, context)
> +    machines_url = context.url("/systems/#{instance_id}/machines")
> +    unless CIMI::Model.const_defined?('SystemMachineCollection')
> +      collection_class = CIMI::Model::Collection.generate(self)
> +    else
> +      collection_class = CIMI::Model::SystemMachineCollection
> +    end
> +    collection_class.new(
> +      :id => machines_url,
> +      :name => 'default',
> +      :count => system_machines.size,
> +      :description => "Machine collection for System #{instance_id}",
> +      :entries => system_machines,
> +      :operations => [{ :href =>
> machines_url.singularize+"_attach", :rel => "add" }]
> +    )
> +  end
> +
> +end
> diff --git a/server/lib/cimi/models/system_network.rb
> b/server/lib/cimi/models/system_network.rb
> new file mode 100644
> index 0000000..df3f831
> --- /dev/null
> +++ b/server/lib/cimi/models/system_network.rb
> @@ -0,0 +1,90 @@
> +# 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::Model::SystemNetwork < CIMI::Model::Base
> +
> +  href :network
> +
> +  array :operations do
> +    scalar :rel, :href
> +  end
> +
> +  def self.find(instance_id, context, id=:all)
> +    puts "SystemNetwork#self.find called"
> +    if id == :all
> +      networks =
> context.driver.storage_networks(context.credentials)
> +      networks.inject([]) do |attached, vol|
> +        id = context.system_url(instance_id)+"/networks/#{vol.id}"
> +        attached <<  self.new(
> +          :id => id,
> +          :name => vol.id,
> +          :description => "SystemNetwork #{vol.id} for System
> #{instance_id}",
> +          :created => vol.created.nil? ? nil :
> Time.parse(vol.created).xmlschema,
> +          :initial_location => vol.device,
> +          :network => {:href=>context.network_url(vol.id)},
> +          :operations => [{:href=>id, :rel => "delete" }]
> +          ) if vol.instance_id == instance_id
> +        attached
> +      end
> +    else
> +      vol = context.driver.storage_network(context.credentials,
> {:id=>id})
> +      id = context.system_url(instance_id)+"/networks/#{vol.id}"
> +      raise CIMI::Model::NotFound unless vol.instance_id ==
> instance_id
> +      self.new(
> +        :id => id,
> +        :name => vol.id,
> +        :description => "SystemNetwork #{vol.id} for System
> #{instance_id}",
> +        :created => vol.created.nil? ? nil :
> Time.parse(vol.created).xmlschema,
> +        :initial_location => vol.device,
> +        :network => {:href=>context.network_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["network"].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["network"]["href"].split("/").last
> +    location = json["initialLocation"]
> +    [vol_id, location]
> +  end
> +
> +
> +  def self.collection_for_instance(instance_id, context)
> +    system_networks = self.find(instance_id, context)
> +    networks_url = context.url("/systems/#{instance_id}/networks")
> +    unless CIMI::Model.const_defined?('SystemNetworkCollection')
> +      collection_class = CIMI::Model::Collection.generate(self)
> +    else
> +      collection_class = CIMI::Model::SystemNetworkCollection
> +    end
> +    collection_class.new(
> +      :id => networks_url,
> +      :name => 'default',
> +      :count => system_networks.size,
> +      :description => "Network collection for System #{instance_id}",
> +      :entries => system_networks,
> +      :operations => [{ :href =>
> networks_url.singularize+"_attach", :rel => "add" }]
> +    )
> +  end
> +
> +end
> diff --git a/server/lib/cimi/models/system_system.rb
> b/server/lib/cimi/models/system_system.rb
> new file mode 100644
> index 0000000..41f9ae7
> --- /dev/null
> +++ b/server/lib/cimi/models/system_system.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::Model::SystemSystem < CIMI::Model::Base
> +
> +  href :system
> +
> +  array :operations do
> +    scalar :rel, :href
> +  end
> +
> +  def self.find(instance_id, context, id=:all)
> +    puts "SystemSystem#self.find called"
> +  end
> +
> +
> +  def self.collection_for_instance(instance_id, context)
> +  end
> +
> +end
> diff --git a/server/lib/cimi/models/system_template.rb
> b/server/lib/cimi/models/system_template.rb
> new file mode 100644
> index 0000000..9cfc64c
> --- /dev/null
> +++ b/server/lib/cimi/models/system_template.rb
> @@ -0,0 +1,66 @@
> +# 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::Model::SystemTemplate < CIMI::Model::Base
> +
> +  acts_as_root_entity
> +
> +  array :component_descriptors do
> +    text :name, :description
> +    hash :properties
> +    text :type
> +    scalar :component_template #or :class => CIMI::Model::Base ?
> +    text :quantity
> +  end
> +
> +  array :meter_templates do
> +    scalar :href
> +  end
> +
> +  href :event_log_template
> +
> +  array :operations do
> +    scalar :rel, :href
> +  end
> +
> +  class << self
> +    def find(id, context)
> +  puts "system_template#self.find called"
> +      templates = []
> +      if id == :all
> +        templates =
> context.driver.system_templates(context.credentials, {:env=>context})
> +puts "Templates from driver #{templates.size}"
> +      else
> +        template =
> context.driver.system_templates(context.credentials,
> {:env=>context, :id=>id})
> +        raise CIMI::Model::NotFound unless template
> +        template
> +      end
> +    end
> +
> +    def create_from_json(body, context)
> +      #todo: mfojtik and lutter are refactoring this mechanism
> +    end
> +
> +    def create_from_xml(body, context)
> +      #todo: mfojtik and lutter are refactoring this mechanism
> +    end
> +
> +    def delete!(id, context)
> +      context.driver.destroy_system_template(context.credentials,
> id)
> +    end
> +
> +  end
> +
> +end
> diff --git a/server/lib/cimi/models/system_volume.rb
> b/server/lib/cimi/models/system_volume.rb
> new file mode 100644
> index 0000000..3433402
> --- /dev/null
> +++ b/server/lib/cimi/models/system_volume.rb
> @@ -0,0 +1,90 @@
> +# 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::Model::SystemVolume < CIMI::Model::Base
> +
> +  href :volume
> +
> +  array :operations do
> +    scalar :rel, :href
> +  end
> +
> +  def self.find(instance_id, context, id=:all)
> +    puts "system_volume#self.find called"
> +    if id == :all
> +      volumes = context.driver.storage_volumes(context.credentials)
> +      volumes.inject([]) do |attached, vol|
> +        id = context.system_url(instance_id)+"/volumes/#{vol.id}"
> +        attached <<  self.new(
> +          :id => id,
> +          :name => vol.id,
> +          :description => "SystemVolume #{vol.id} for System
> #{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.system_url(instance_id)+"/volumes/#{vol.id}"
> +      raise CIMI::Model::NotFound unless vol.instance_id ==
> instance_id
> +      self.new(
> +        :id => id,
> +        :name => vol.id,
> +        :description => "SystemVolume #{vol.id} for System
> #{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)
> +    system_volumes = self.find(instance_id, context)
> +    volumes_url = context.url("/systems/#{instance_id}/volumes")
> +    unless CIMI::Model.const_defined?('SystemVolumeCollection')
> +      collection_class = CIMI::Model::Collection.generate(self)
> +    else
> +      collection_class = CIMI::Model::SystemVolumeCollection
> +    end
> +    collection_class.new(
> +      :id => volumes_url,
> +      :name => 'default',
> +      :count => system_volumes.size,
> +      :description => "Volume collection for System #{instance_id}",
> +      :entries => system_volumes,
> +      :operations => [{ :href =>
> volumes_url.singularize+"_attach", :rel => "add" }]
> +    )
> +  end
> +
> +end
> diff --git
> a/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
> b/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
> new file mode 100644
> index 0000000..450233d
> --- /dev/null
> +++
> b/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
> @@ -0,0 +1,12 @@
> +{ "id": "http://cimi.example.org/systems/template1",
> +  "name": "system1",
> +  "description": "the first system",
> +  "created": "Fri Feb 08 15:25:41 EET 2013",
> +  "state": "STOPPED",
> +  "machines": { "href":
> "http://cimi.example.org/systems/87654/machines"},
> +  "networks": { "href":
> "http://cimi.example.org/systems/87654/networks"},
> +  "operations": [
> +    { "rel": "edit", "href":
> "http://cimi.example.org/networks/network1" },
> +    { "rel": "delete", "href":
> "http://cimi.example.org/networks/network1" }
> +  ]
> +}
> diff --git
> a/server/lib/deltacloud/drivers/mock/data/cimi/system_template/templ
> ate1.json
> b/server/lib/deltacloud/drivers/mock/data/cimi/system_template/templ
> ate1.json
> new file mode 100644
> index 0000000..0672df1
> --- /dev/null
> +++
> b/server/lib/deltacloud/drivers/mock/data/cimi/system_template/templ
> ate1.json
> @@ -0,0 +1,27 @@
> +{ "id": "http://cimi.example.org/system_templates/template1",
> +  "name": "system template 1",
> +  "description": "A mock system template",
> +  "created": "Fri Feb 08 12:15:15 EET 2013",
> +  "componentDescriptors": [
> +    { "name": "my machine",
> +      "description": "an inline mock machine template",
> +      "type": "http://schemas.dmtf.org/cimi/1/Machine",
> +      "machineTemplate": {
> +        "name": "machine in mock system",
> +        "description": "machine in ststem",
> +        "machineConfig": "http://example.com/configs/m1-small",
> +        "machineImage": "http://example.com/images/img1"
> +      }
> +    },
> +    { "name": "my network",
> +      "description": "a reference to an existing mock network
template",
> +      "type": "http://schemas.dmtf.org/cimi/1/Network",
> +      "networkTemplate": {
> +        "href":
> "http://cimi.example.org/network_templates/template1"
> +      }
> +    }
> +  ],
> +  "operations": [
> +    { "rel": "edit", "href":
> "http://cimi.example.org/network_templates/template1" },
> +    { "rel": "delete", "href":
> "http://cimi.example.org/network_templates/template1" }]
> +}
> diff --git a/server/lib/deltacloud/drivers/mock/mock_client.rb
> b/server/lib/deltacloud/drivers/mock/mock_client.rb
> index 449b6a8..d7796a2 100644
> --- a/server/lib/deltacloud/drivers/mock/mock_client.rb
> +++ b/server/lib/deltacloud/drivers/mock/mock_client.rb
> @@ -92,7 +92,9 @@ module Deltacloud::Drivers::Mock
>      end
> 
>      def load_all_cimi(model_name)
> +    puts "dir: #{File::join(cimi_dir(model_name), "*.json")}"
>          model_files = Dir[File::join(cimi_dir(model_name), "*.json")]
> +        puts "model_files: #{model_files}"
>          model_files.map{|f| File.read(f)}
>      end
> 
> diff --git
> a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
> b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
> index 336f77b..57ea5ef 100644
> --- a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
> +++ b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
> @@ -20,6 +20,31 @@
>  module Deltacloud::Drivers::Mock
> 
>    class MockDriver < Deltacloud::BaseDriver
> +
> +    def systems(credentials, opts={})
> +      check_credentials(credentials)
> +      if opts[:id].nil?
> +        systems = @client.load_all_cimi(:system).map{|sys|
> CIMI::Model::System.from_json(sys)}
> +        systems.map{|sys|convert_cimi_mock_urls(:system,
> sys ,opts[:env])}.flatten
> +      else
> +        system =
> CIMI::Model::System.from_json(@client.load_cimi(:system, opts[:id]))
> +        convert_cimi_mock_urls(:system, system, opts[:env])
> +      end
> +    end
> +
> +    def system_templates(credentials, opts={})
> +      check_credentials(credentials)
> +      puts "reached mock's system_templates with opts: #{opts}"
> +      if opts[:id].nil?
> +        system_templates =
> @client.load_all_cimi(:system_template).map{|sys_templ|
> CIMI::Model::SystemTemplate.from_json(sys_templ)}
> +        puts "raw templates from files: #{system_templates}"
> +
> system_templates.map{|sys_templ|convert_cimi_mock_urls(:system_templ
> ate, sys_templ, opts[:env])}.flatten
> +      else
> +        system_template =
> CIMI::Model::SystemTemplate.from_json(@client.load_cimi(:system_temp
> late, opts[:id]))
> +        convert_cimi_mock_urls(:system_template, system_template,
> opts[:env])
> +      end
> +    end
> +
>      def networks(credentials, opts={})
>        check_credentials(credentials)
>        if opts[:id].nil?
> @@ -138,6 +163,8 @@ module Deltacloud::Drivers::Mock
>              end
>          end
>        end
> +      puts "cimi_object.name = #{cimi_object.name}"
> +      puts "context = #{context}"
>        object_url = context.send(:"#{model_name}_url",
> cimi_object.name)
>        cimi_object.id=object_url
>        cimi_object.operations.each{|op| op.href=object_url  }
> --
> 1.8.0.msysgit.0
> 
> 



Re: [PATCH] CIMI: adding system support

Posted by David Lutterkort <lu...@redhat.com>.
On Sat, 2013-02-09 at 22:51 +1100, Koper, Dies wrote:
> > As a general comment, try adding as little of the System* objects in one
> > patch as possible, again, to make reviewing easier. I haven't looked in
> > detail if that makes sense here or not, but it would be nice if it did,
> > and there's nothing wrong with a CIMI provider that only has System, but
> > none of the other System* collections.
> 
> It is my understanding that a System references its components
> (machines, etc.) through System* collections, so without the System*
> collections all we'd have is a System class with a name, description
> and state, but no containing machines, etc.
> So I assume leaving them out here doesn't make sense?

All those System* resources are optional; it's for example completely
legal to just support systems that can only contain machines (it's even
legal to have systems that contain no other resources, but that would be
kina silly)

So I would start with that: systems that only contain one kind of
resource and expand from there.

David



RE: [PATCH] CIMI: adding system support

Posted by "Koper, Dies" <di...@fast.au.fujitsu.com>.
Thanks!

> > +++ b/server/lib/cimi/collections/system_templates.rb
> 
> Nothing wrong with what you did here, but I am wondering if there is
> anything we can do to reduce this sort of boilerplate. Most of our
> collections look exactly the same ...

I was planning to suggest the same, after I confirmed the copying and pasting I did is actually correct.
I suppose we have two types of models/collections, the ones that are implemented directly in the drivers (like system, I suppose also meter and eventlog) and the ones that are mapped to Deltacloud's models first (machines/instances, images, etc.). Especially in the former case but maybe also in the latter case most of the code is the same.
I based this and system.rb on I believe machine.rb and all I did was rename machine to system.

> The puts just before the else is where things go wrong: without the
> puts, the value of the if branch is whatever is assigned to systems,
> which in turn is what gets returned from self.find - by inserting the
> puts, you are now returning nil. Put a line 'systems' just after the
> puts, and things look much better (at least, you're getting a valid
> response back instead of a 500, though it had no systems for me)

Thanks, that worked for me. Now both systems and system_templates are returning an entry for me:

<Collection xmlns="http://schemas.dmtf.org/cimi/1" resourceURI="http://schemas.dmtf.org/cimi/1/SystemCollection">
  <id>http://localhost:3001/cimi/systems</id>
  <count>1</count>
  <System>
    <id>http://localhost:3001/cimi/systems/system1</id>
    <name>system1</name>
    <description>the first system</description>
    <created>Fri Feb 08 15:25:41 EET 2013</created>
    <state>STOPPED</state>
    <systems href="http://localhost:3001/cimi/systems/system1/systems" />
    <machines href="http://cimi.example.org/systems/87654/machines" />
    <volumes href="http://localhost:3001/cimi/systems/system1/volumes" />
    <networks href="http://cimi.example.org/systems/87654/networks" />
    <addresses href="http://localhost:3001/cimi/systems/system1/addresses" />
    <forwardingGroups href="http://localhost:3001/cimi/systems/system1/forwarding_groups" />
    <operation rel="edit" href="http://localhost:3001/cimi/systems/system1" />
    <operation rel="delete" href="http://localhost:3001/cimi/systems/system1" />
  </System>
</Collection>

And

<Collection xmlns="http://schemas.dmtf.org/cimi/1" resourceURI="http://schemas.dmtf.org/cimi/1/SystemTemplateCollection">
  <id>http://localhost:3001/cimi/system_templates</id>
  <count>1</count>
  <SystemTemplate>
    <id>http://localhost:3001/cimi/system_templates/system template 1</id>
    <name>system template 1</name>
    <description>A mock system template</description>
    <created>Fri Feb 08 12:15:15 EET 2013</created>
    <componentDescriptor>
      <name>my machine</name>
      <description>an inline mock machine template</description>
      <type>http://schemas.dmtf.org/cimi/1/Machine</type>
    </componentDescriptor>
    <componentDescriptor>
      <name>my network</name>
      <description>a reference to an existing mock network template</description>
      <type>http://schemas.dmtf.org/cimi/1/Network</type>
    </componentDescriptor>
    <operation rel="edit" href="http://localhost:3001/cimi/system_templates/system template 1" />
    <operation rel="delete" href="http://localhost:3001/cimi/system_templates/system template 1" />
  </SystemTemplate>
</Collection>

The first time I ran it it didn't work for me because I needed to copy the json files from mock/data to my local /var/tmp/... folder. Maybe that's why it didn't work for you?

I don't believe this response XML is correct so I'll look at that first.

> As a general comment, try adding as little of the System* objects in one
> patch as possible, again, to make reviewing easier. I haven't looked in
> detail if that makes sense here or not, but it would be nice if it did,
> and there's nothing wrong with a CIMI provider that only has System, but
> none of the other System* collections.

It is my understanding that a System references its components (machines, etc.) through System* collections, so without the System* collections all we'd have is a System class with a name, description and state, but no containing machines, etc.
So I assume leaving them out here doesn't make sense?

Cheers,
Dies Koper

Re: [PATCH] CIMI: adding system support

Posted by David Lutterkort <lu...@redhat.com>.
On Fri, 2013-02-08 at 22:44 +1100, diesk@fast.au.fujitsu.com wrote:
> From: Dies Koper <di...@fast.au.fujitsu.com>

You killed yourself with debug prints; I'll point the exact place out
below. But I also have a couple more comments.

> diff --git a/server/lib/cimi/collections/addresses.rb b/server/lib/cimi/collections/addresses.rb
> index 9ea1764..a51e658 100644
> --- a/server/lib/cimi/collections/addresses.rb
> +++ b/server/lib/cimi/collections/addresses.rb
> @@ -20,7 +20,7 @@ module CIMI::Collections
>  
>      collection :addresses do
>  
> -      description 'An Address represents an IP address, and its associated metdata, for a particular Network.'
> +      description 'An Address represents an IP address, and its associated metadata, for a particular Network.'
>  
>        operation :index, :with_capability => :addresses do
>          description 'List all Addresses in the AddressCollection'
> diff --git a/server/lib/cimi/collections/machines.rb b/server/lib/cimi/collections/machines.rb
> index 5718f46..9a71bb1 100644
> --- a/server/lib/cimi/collections/machines.rb
> +++ b/server/lib/cimi/collections/machines.rb
> @@ -85,7 +85,7 @@ module CIMI::Collections
>        end
>  
>        action :restart, :with_capability => :reboot_instance do
> -        description "Start specific machine."
> +        description "Restart specific machine."
>          param :id,          :string,    :required
>          control do
>            machine = Machine.find(params[:id], self)

These fixes should go into separate patches (whether one or two is up to
you) But there's no shame in sending one line patches - it's actually
nice because they are much easier to review. It's very important that
each patch is as small as possible for that reason. 'Small' here means
the smallest change that will allow the tests still to pass.

> diff --git a/server/lib/cimi/collections/system_templates.rb b/server/lib/cimi/collections/system_templates.rb
> new file mode 100644
> index 0000000..88fbe30
> --- /dev/null
> +++ b/server/lib/cimi/collections/system_templates.rb

Nothing wrong with what you did here, but I am wondering if there is
anything we can do to reduce this sort of boilerplate. Most of our
collections look exactly the same ...

> diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
> index c74b8c3..2c49c75 100644
> --- a/server/lib/cimi/models/base.rb
> +++ b/server/lib/cimi/models/base.rb
> @@ -63,7 +63,7 @@ require_relative '../helpers/database_helper'
>  #   [struct(name, opts, &block)]
>  #     A structured subobject; the block defines the schema of the
>  #     subobject. The +:content+ option can be used to specify the attribute
> -#     that should receive the content of hte corresponding XML element
> +#     that should receive the content of the corresponding XML element
>  #   [array(name, opts, &block)]
>  #     An array of structured subobjects; the block defines the schema of
>  #     the subobjects.
> @@ -86,7 +86,7 @@ module CIMI::Model
>      #
>      # Common attributes for all resources
>      #
> -    text :id, :name, :description, :created
> +    text :id, :name, :description, :created, :updated

Another change that could go into a separate patch - you are right that
we are missing these from the common attributes (section 5.10.1 in the
spec)

> diff --git a/server/lib/cimi/models/system.rb b/server/lib/cimi/models/system.rb
> new file mode 100644
> index 0000000..619e7a9
> --- /dev/null
> +++ b/server/lib/cimi/models/system.rb
...
> +  def self.find(id, context)
> +  puts "system#self.find called"
> +    systems = []
> +    if id == :all
> +      systems = context.driver.systems(context.credentials, {:env=>context})
> +puts "systems from driver #{systems.size}"
> +    else
> +      system = context.driver.system(context.credentials, {:env=>context, :id=>id})
> +      raise CIMI::Model::NotFound unless system
> +      system
> +    end
> +  end

The puts just before the else is where things go wrong: without the
puts, the value of the if branch is whatever is assigned to systems,
which in turn is what gets returned from self.find - by inserting the
puts, you are now returning nil. Put a line 'systems' just after the
puts, and things look much better (at least, you're getting a valid
response back instead of a 500, though it had no systems for me)

As a general comment, try adding as little of the System* objects in one
patch as possible, again, to make reviewing easier. I haven't looked in
detail if that makes sense here or not, but it would be nice if it did,
and there's nothing wrong with a CIMI provider that only has System, but
none of the other System* collections.

David