deltacloud-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mfoj...@apache.org
Subject [44/50] [abbrv] CIMI: Moved code from CIMI server.rb and split it to smaller collections like in Deltacloud
Date Tue, 22 May 2012 20:19:38 GMT
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/model/vsp_template_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/model/vsp_template_collection.rb b/server/lib/cimi/model/vsp_template_collection.rb
deleted file mode 100644
index 4acb74e..0000000
--- a/server/lib/cimi/model/vsp_template_collection.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# 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::VSPTemplateCollection < CIMI::Model::Base
-
-  CIMI::Model.register_as_root_entity! "VSPTemplates"
-
-  array :vsp_templates do
-    scalar :href
-  end
-
-  def self.default(context)
-    self.new(
-      :id => context.vsp_templates_url,
-      :name => 'default',
-      :created => Time.now,
-      :description => "#{context.driver.name.capitalize} VSPTemplateCollection",
-      :vsp_templates => VSPTemplate.all_uri(context)
-    )
-  end
-
-end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
new file mode 100644
index 0000000..b0793ee
--- /dev/null
+++ b/server/lib/cimi/models.rb
@@ -0,0 +1,75 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless require_relatived by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../deltacloud/drivers/features'
+
+# Declare namespace for CIMI models
+#
+
+module CIMI
+  module Model; end
+
+  class FakeCollection
+    extend Sinatra::Rabbit::Features
+    include Deltacloud::InstanceFeatures
+  end
+end
+
+require_relative './models/schema'
+require_relative './models/base'
+require_relative './models/errors'
+require_relative './models/entity_metadata'
+require_relative './models/entity_metadata_collection'
+require_relative './models/cloud_entry_point'
+require_relative './models/machine_template'
+require_relative './models/machine_image'
+require_relative './models/machine_configuration'
+require_relative './models/action'
+require_relative './models/machine'
+require_relative './models/volume'
+require_relative './models/machine_admin'
+require_relative './models/volume_configuration'
+require_relative './models/volume_image'
+require_relative './models/volume_template'
+require_relative './models/machine_template_collection'
+require_relative './models/machine_image_collection'
+require_relative './models/machine_configuration_collection'
+require_relative './models/machine_collection'
+require_relative './models/volume_collection'
+require_relative './models/machine_admin_collection'
+require_relative './models/volume_configuration_collection'
+require_relative './models/volume_image_collection'
+require_relative './models/volume_template_collection'
+require_relative './models/network'
+require_relative './models/network_collection'
+require_relative './models/network_configuration'
+require_relative './models/network_configuration_collection'
+require_relative './models/network_template'
+require_relative './models/network_template_collection'
+require_relative './models/routing_group'
+require_relative './models/routing_group_collection'
+require_relative './models/routing_group_template'
+require_relative './models/routing_group_template_collection'
+require_relative './models/vsp'
+require_relative './models/vsp_collection'
+require_relative './models/vsp_configuration'
+require_relative './models/vsp_configuration_collection'
+require_relative './models/vsp_template'
+require_relative './models/vsp_template_collection'
+require_relative './models/address'
+require_relative './models/address_collection'
+require_relative './models/address_template'
+require_relative './models/address_template_collection'

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/action.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/action.rb b/server/lib/cimi/models/action.rb
new file mode 100644
index 0000000..c1c9908
--- /dev/null
+++ b/server/lib/cimi/models/action.rb
@@ -0,0 +1,24 @@
+# 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::Action < CIMI::Model::Base
+
+  text :action
+
+  def name
+    action.split('/').last.strip.intern
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/address.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/address.rb b/server/lib/cimi/models/address.rb
new file mode 100644
index 0000000..f9e10a1
--- /dev/null
+++ b/server/lib/cimi/models/address.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.
+
+class CIMI::Model::Address < CIMI::Model::Base
+
+  text :ip
+
+  text :hostname
+
+  text :allocation
+
+  text :default_gateway
+
+  text :dns
+
+  text :mac_address
+
+  text :protocol
+
+  text :mask
+
+  href :network
+
+  href :resource
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.addresses(context.credentials, {:env=>context})
+    else
+      context.driver.addresses(context.credentials, {:id=>id, :env=>context})
+    end
+  end
+
+  def self.create(request_body, context, type)
+    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false, "NormaliseSpace"=>2}) : JSON.parse(request_body)
+    if input["addressTemplate"]["href"] #by reference
+      address_template = CIMI::Model::AddressTemplate.find(context.href_id(input["addressTemplate"]["href"], :address_templates), context)
+    else
+      case type
+        when :json
+          address_template = CIMI::Model::AddressTemplate.from_json(JSON.generate(input["addressTemplate"]))
+        when :xml
+          xml = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
+          address_template = CIMI::Model::AddressTemplate.from_xml(XmlSimple.xml_out(xml["addressTemplate"][0]))
+      end
+    end
+    params = {:name=>input["name"], :description=>input["description"], :address_template=>address_template, :env=>context }
+    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
+    context.driver.create_address(context.credentials, params)
+  end
+
+  def self.delete!(id, context)
+    context.driver.delete_address(context.credentials, id)
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/address_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/address_collection.rb b/server/lib/cimi/models/address_collection.rb
new file mode 100644
index 0000000..eef6c51
--- /dev/null
+++ b/server/lib/cimi/models/address_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::AddressCollection < CIMI::Model::Base
+
+  act_as_root_entity :address
+
+  array :addresses do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.addresses_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} AddressCollection",
+      :addresses => CIMI::Model::Address.all(context).map { |addr| { :href => addr.id } }
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/address_template.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/address_template.rb b/server/lib/cimi/models/address_template.rb
new file mode 100644
index 0000000..9d2c409
--- /dev/null
+++ b/server/lib/cimi/models/address_template.rb
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::AddressTemplate < CIMI::Model::Base
+
+  text :ip
+
+  text :hostname
+
+  text :allocation
+
+  text :default_gateway
+
+  text :dns
+
+  text :mac_address
+
+  text :protocol
+
+  text :mask
+
+  href :network
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.address_templates(context.credentials, {:env=>context})
+    else
+      context.driver.address_templates(context.credentials, {:id=>id, :env=>context})
+    end
+  end
+
+  def self.create(request_body, context, type)
+  end
+
+  def self.delete!(id, context)
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/address_template_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/address_template_collection.rb b/server/lib/cimi/models/address_template_collection.rb
new file mode 100644
index 0000000..3bb95cd
--- /dev/null
+++ b/server/lib/cimi/models/address_template_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::AddressTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :address_template
+
+  array :address_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.address_templates_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} AddressTemplateCollection",
+      :address_templates => CIMI::Model::AddressTemplate.all(context).map { |addr| { :href => addr.id } }
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/base.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
new file mode 100644
index 0000000..16812ac
--- /dev/null
+++ b/server/lib/cimi/models/base.rb
@@ -0,0 +1,249 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+require 'xmlsimple'
+require 'json'
+
+# The base class for any CIMI object that we either read from a request or
+# write as a response. This class handles serializing/deserializing XML and
+# JSON into a common form.
+#
+# == Defining the schema
+#
+# The conversion of XML and JSON into internal objects is based on a schema
+# that is defined through a DSL:
+#
+#   class Machine < CIMI::Model::Base
+#     text :status
+#     href :meter
+#     array :volumes do
+#       scalar :href, :attachment_point, :protocol
+#     end
+#   end
+#
+# The DSL automatically takes care of converting identifiers from their
+# underscored form to the camel-cased form used by CIMI. The above class
+# can be used in the following way:
+#
+#   machine = Machine.from_xml(some_xml)
+#   if machine.status == "UP"
+#     ...
+#   end
+#   sda = machine.volumes.find { |v| v.attachment_point == "/dev/sda" }
+#   handle_meter(machine.meter.href)
+#
+# The keywords for the DSL are
+#   [scalar(names, ...)]
+#     Define a scalar attribute; in JSON, this is represented as a string
+#     property. In XML, this can be represented in a number of ways,
+#     depending on whether the option :text is set:
+#       * :text not set: attribute on the enclosing element
+#       * :text == :direct: the text content of the enclosing element
+#       * :text == :nested: the text content of an element +<name>...</name>+
+#   [text(names)]
+#     A shorthand for +scalar(names, :text => :nested)+, i.e., for
+#     attributes that in XML are represented by their own tags
+#   [href(name)]
+#     A shorthand for +struct name { scalar :href }+; in JSON, this is
+#     represented as +{ name: { "href": string } }+, and in XML as +<name
+#     href="..."/>+
+#   [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
+#   [array(name, opts, &block)]
+#     An array of structured subobjects; the block defines the schema of
+#     the subobjects.
+
+module CIMI::Model
+
+  def self.register_as_root_entity!(name)
+    @root_entities ||= []
+    @root_entities << name
+    unless CIMI::Model::CloudEntryPoint.href_defined?(name)
+      CIMI::Model::CloudEntryPoint.send(:href, name.underscore)
+    end
+  end
+
+  def self.root_entities
+    @root_entities || []
+  end
+
+end
+
+class CIMI::Model::Base
+
+  #
+  # We keep the values of the attributes in a hash
+  #
+  attr_reader :attribute_values
+
+  # Keep the list of all attributes in an array +attributes+; for each
+  # attribute, we also define a getter and a setter to access/change the
+  # value for that attribute
+  class << self
+    def base_schema
+      @schema ||= CIMI::Model::Schema.new
+    end
+
+    def clone_base_schema
+      @schema_duped = true
+      @schema = Marshal::load(Marshal.dump(superclass.base_schema))
+    end
+
+    def base_schema_cloned?
+      @schema_duped
+    end
+
+    private :'clone_base_schema', :'base_schema_cloned?'
+
+    def inherited(child)
+      child.instance_eval do
+        def schema
+          base_schema_cloned? ? @schema : clone_base_schema
+        end
+      end
+    end
+
+    def add_attributes!(names, attr_klass, &block)
+      if self.respond_to? :schema
+        schema.add_attributes!(names, attr_klass, &block)
+      else
+        base_schema.add_attributes!(names, attr_klass, &block)
+      end
+      names.each do |name|
+        define_method(name) { @attribute_values[name] }
+        define_method(:"#{name}=") { |newval| @attribute_values[name] = newval }
+      end
+    end
+
+    # Return Array of links to current CIMI object
+    def all_uri(context)
+      self.all(context).map { |e| { :href => e.id } }
+    end
+  end
+
+  extend CIMI::Model::Schema::DSL
+
+  def [](a)
+    @attribute_values[a]
+  end
+
+  def []=(a, v)
+    @attribute_values[a] = v
+  end
+
+  #
+  # Factory methods
+  #
+  def initialize(values = {})
+    @attribute_values = values
+  end
+
+  # Construct a new object from the XML representation +xml+
+  def self.from_xml(text)
+    xml = XmlSimple.xml_in(text, :force_content => true)
+    model = self.new
+    @schema.from_xml(xml, model)
+    model
+  end
+
+  # Construct a new object
+  def self.from_json(text)
+    json = JSON::parse(text)
+    model = self.new
+    @schema.from_json(json, model)
+    model
+  end
+
+  #
+  # Serialize
+  #
+
+  def self.xml_tag_name
+    self.name.split("::").last
+  end
+
+  def self.to_json(model)
+    JSON::unparse(@schema.to_json(model))
+  end
+
+  def self.to_xml(model)
+    xml = @schema.to_xml(model)
+    xml["xmlns"] = "http://www.dmtf.org/cimi"
+    XmlSimple.xml_out(xml, :root_name => xml_tag_name)
+  end
+
+  def to_json
+    self.class.to_json(self)
+  end
+
+  def to_xml
+    self.class.to_xml(self)
+  end
+
+  #
+  # Common attributes for all resources
+  #
+  text :id, :name, :description, :created
+
+  # FIXME: this doesn't match with JSON
+  hash :property, :content => :value do
+    scalar :name
+  end
+
+  def self.act_as_root_entity(name=nil)
+    if name
+      name = name.to_s.camelize.pluralize
+    else
+      name = xml_tag_name.pluralize.uncapitalize
+    end
+    CIMI::Model.register_as_root_entity! name
+  end
+
+  def self.all(_self); find(:all, _self); end
+
+  def filter_by(filter_opts)
+    return self if filter_opts.nil?
+    return filter_attributes(filter_opts.split(',').map{ |a| a.intern }) if filter_opts.include? ','
+    case filter_opts
+      when /^([\w\_]+)$/ then filter_attributes([$1.intern])
+      when /^([\w\_]+)\[(\d+\-\d+)\]$/ then filter_by_arr_range($1.intern, $2)
+      when /^([\w\_]+)\[(\d+)\]$/ then filter_by_arr_index($1.intern, $2)
+      else self
+    end
+  end
+
+  private
+
+  def filter_attributes(attr_list)
+    attrs = attr_list.inject({}) do |result, attr|
+      result[attr] = self.send(attr) if self.respond_to?(attr)
+      result
+    end
+    self.class.new(attrs)
+  end
+
+  def filter_by_arr_index(attr, filter)
+    return self unless self.respond_to?(attr)
+    self.class.new(attr => [self.send(attr)[filter.to_i]])
+  end
+
+  def filter_by_arr_range(attr, filter)
+    return self unless self.respond_to?(attr)
+    filter = filter.split('-').inject { |s,e| s.to_i..e.to_i }
+    self.class.new(attr => self.send(attr)[filter])
+  end
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/cloud_entry_point.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/cloud_entry_point.rb b/server/lib/cimi/models/cloud_entry_point.rb
new file mode 100644
index 0000000..ffe1ef5
--- /dev/null
+++ b/server/lib/cimi/models/cloud_entry_point.rb
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::CloudEntryPoint < CIMI::Model::Base
+
+  array :entity_metadata do
+    scalar :href
+  end
+
+  def self.create(context)
+    self.new(entities(context).merge({
+      :name => context.driver.name,
+      :description => "Cloud Entry Point for the Deltacloud #{context.driver.name} driver",
+      :id => context.cloudEntryPoint_url,
+      :created => Time.now,
+      :entity_metadata => CIMI::Model::EntityMetadata.all_uri(context)
+    }))
+  end
+
+  # Return an Hash of the CIMI root entities used in CloudEntryPoint
+  def self.entities(context)
+    CIMI::Model.root_entities.inject({}) do |result, entity|
+      result[entity.underscore] = { :href => context.send(:"#{entity.underscore}_url") }
+      result
+    end
+  end
+
+  private
+
+  def self.href_defined?(entity)
+    true if schema.attribute_names.include? entity.underscore
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/entity_metadata.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/entity_metadata.rb b/server/lib/cimi/models/entity_metadata.rb
new file mode 100644
index 0000000..5455c75
--- /dev/null
+++ b/server/lib/cimi/models/entity_metadata.rb
@@ -0,0 +1,84 @@
+# 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::EntityMetadata < CIMI::Model::Base
+
+  text :type_uri
+
+  array :attributes do
+    scalar :name
+    scalar :namespace
+    scalar :type
+    scalar :required
+    scalar :constraints
+  end
+
+  array :operations do
+    scalar :name
+    scalar :uri
+    scalar :description
+    scalar :method
+    scalar :input_message
+    scalar :output_message
+  end
+
+  def self.find(id, context)
+    entity_metadata = []
+    if id == :all
+      CIMI::Model.root_entities.each do |entity|
+        entity_class = CIMI::Model.const_get("#{entity.singularize}")
+        entity_metadata << entity_class.create_entity_metadata(context) if entity_class.respond_to?(:create_entity_metadata)
+      end
+      return entity_metadata
+    else
+      entity_class = CIMI::Model.const_get("#{id.camelize}")
+      if entity_class.respond_to?(:create_entity_metadata)
+        entity_class.create_entity_metadata(context)
+      end
+    end
+  end
+
+  def self.metadata_from_deltacloud_features(cimi_entity, dcloud_entity, context)
+    deltacloud_features = context.driver.class.features_for(dcloud_entity)
+    metadata_attributes = deltacloud_features.map{|f| attributes_from_feature(f)}
+    from_feature(cimi_entity, context, metadata_attributes.flatten!)
+  end
+
+  def includes_attribute?(attribute)
+    self.attributes.any?{|attr| attr[:name] == attribute}
+  end
+
+  private
+
+  def self.attributes_from_feature(feature)
+    feature = CIMI::FakeCollection.feature(feature)
+    feature.operations.first.params_array.map do |p|
+      {
+        :name=> p.name,
+        :type=> "xs:string",
+        :required=> p.required? ? "true" : "false",
+        :constraints=> (feature.constraints.empty? ? (feature.description.nil? ? "" : feature.description): feature.constraints)
+      }
+    end
+  end
+
+  def self.from_feature(cimi_entity, context, metadata_attributes)
+    self.new(:name => cimi_entity, :uri=>"#{context.entity_metadata_url}/#{cimi_entity.underscore}",
+             :type_uri=> context.send("#{cimi_entity.pluralize.underscore}_url"),
+             :attributes => metadata_attributes)
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/entity_metadata_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/entity_metadata_collection.rb b/server/lib/cimi/models/entity_metadata_collection.rb
new file mode 100644
index 0000000..595b502
--- /dev/null
+++ b/server/lib/cimi/models/entity_metadata_collection.rb
@@ -0,0 +1,31 @@
+# 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::EntityMetadataCollection < CIMI::Model::Base
+
+  array :entity_metadata do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.entity_metadata_url,
+      :name => 'default',
+      :created => Time.now,
+      :entity_metadata => CIMI::Model::EntityMetadata.all_uri(context)
+   )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/errors.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/errors.rb b/server/lib/cimi/models/errors.rb
new file mode 100644
index 0000000..7c090ed
--- /dev/null
+++ b/server/lib/cimi/models/errors.rb
@@ -0,0 +1,48 @@
+# 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::Model
+
+  class NotFound < StandardError
+    attr_accessor :code
+
+    def initialize
+      super("Requested Entity Not Found")
+      self.code = 404
+    end
+
+  end
+
+  class BadRequest < StandardError
+    attr_accessor :code
+    def initialize(msg="")
+      super(msg)
+      self.code=400
+    end
+  end
+
+  class NotImplemented < StandardError
+    attr_accessor :code
+
+    def initialize
+      super("Requested operation is not implemented by backend provider")
+      self.code = 501
+    end
+
+  end
+
+end
+
+

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine.rb b/server/lib/cimi/models/machine.rb
new file mode 100644
index 0000000..0540bd8
--- /dev/null
+++ b/server/lib/cimi/models/machine.rb
@@ -0,0 +1,227 @@
+# 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::Machine < CIMI::Model::Base
+
+  text :state
+  text :cpu
+
+  struct :memory do
+    scalar :quantity
+    scalar :units
+  end
+
+  href :event_log
+
+  array :disks do
+    struct :capacity do
+      scalar :quantity
+      scalar :units
+    end
+    scalar :format
+    scalar :attachment_point
+  end
+
+  array :volumes do
+    scalar :href
+    scalar :protocol
+    scalar :attachment_point
+  end
+
+  array :network_interfaces do
+    href :vsp
+    text :hostname, :mac_address, :state, :protocol, :allocation
+    text :address, :default_gateway, :dns, :max_transmission_unit
+  end
+
+  array :meters do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    instances = []
+    if id == :all
+      instances = context.driver.instances(context.credentials)
+      instances.map { |instance| from_instance(instance, context) }.compact
+    else
+      instance = context.driver.instance(context.credentials, :id => id)
+      raise CIMI::Model::NotFound unless instance
+      from_instance(instance, context)
+    end
+  end
+
+  def self.create_from_json(body, context)
+    json = JSON.parse(body)
+    hardware_profile_id = xml['machineTemplate']['machineConfig']["href"].split('/').last
+    image_id = xml['machineTemplate']['machineImage']["href"].split('/').last
+    instance = context.create_instance(context.credentials, image_id, { :hwp_id => hardware_profile_id })
+    from_instance(instance, context)
+  end
+
+  def self.create_from_xml(body, context)
+    xml = XmlSimple.xml_in(body)
+    machine_template = xml['machineTemplate'][0]
+    hardware_profile_id = machine_template['machineConfig'][0]["href"].split('/').last
+    image_id = machine_template['machineImage'][0]["href"].split('/').last
+    additional_params = {}
+    additional_params[:name] =xml['name'][0] if xml['name']
+    if machine_template.has_key? 'machineAdmin'
+      additional_params[:keyname] = machine_template['machineAdmin'][0]["href"].split('/').last
+    end
+    instance = context.driver.create_instance(context.credentials, image_id, {
+      :hwp_id => hardware_profile_id
+    }.merge(additional_params))
+    from_instance(instance, context)
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_instance", context.credentials, self.name)
+        block.callback :success
+      else
+        raise "Operation failed to execute on given Machine"
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_instance(context.credentials, id)
+  end
+
+  def self.create_entity_metadata(context)
+    cimi_entity = self.name.split("::").last
+    metadata = CIMI::Model::EntityMetadata.metadata_from_deltacloud_features(cimi_entity, :instances, context)
+    unless metadata.includes_attribute?(:name)
+      metadata.attributes << {:name=>"name", :required=>"false",
+                   :constraints=>"Determined by the cloud provider", :type=>"xs:string"}
+    end
+    metadata
+  end
+
+  def self.attach_volumes(volumes, context)
+    volumes.each do |vol|
+      context.driver.attach_storage_volume(context.credentials,
+      {:id=>vol[:volume].name, :instance_id=>context.params[:id], :device=>vol[:attachment_point]})
+    end
+    self.find(context.params[:id], context)
+  end
+
+  def self.detach_volumes(volumes, context)
+    volumes.each do |vol|
+      context.driver.detach_storage_volume(context.credentials, {:id=>vol[:volume].name, :instance_id => context.params[:id]})
+    end
+    self.find(context.params[:id], context)
+  end
+
+  private
+
+  def self.from_instance(instance, context)
+    cpu =  memory = disks = (instance.instance_profile.id == "opaque")? "n/a" : nil
+    self.new(
+      :name => instance.id,
+      :description => instance.name,
+      :created => instance.launch_time,
+      :id => context.machine_url(instance.id),
+      :state => convert_instance_state(instance.state),
+      :cpu => cpu || convert_instance_cpu(instance.instance_profile, context),
+      :memory => memory || convert_instance_memory(instance.instance_profile, context),
+      :disks => disks || convert_instance_storage(instance.instance_profile, context),
+      :network_interfaces => convert_instance_addresses(instance),
+      :operations => convert_instance_actions(instance, context),
+      :volumes=>convert_storage_volumes(instance, context),
+      :property => convert_instance_properties(instance, context)
+    )
+  end
+
+  # FIXME: This will convert 'RUNNING' state to 'STARTED'
+  # which is defined in CIMI (p65)
+  #
+  def self.convert_instance_state(state)
+    ('RUNNING' == state) ? 'STARTED' : state
+  end
+
+  def self.convert_instance_properties(instance, context)
+    properties = []
+    properties << { :name => :machine_image, :value => context.machine_image_url(instance.image_id) }
+    if instance.respond_to? :keyname
+      properties << { :name => :machine_admin, :value => context.machine_admin_url(instance.keyname) }
+    end
+    properties
+  end
+
+  def self.convert_instance_cpu(profile, context)
+    cpu_override = profile.overrides.find { |p, v| p == :cpu }
+    if cpu_override.nil?
+      CIMI::Model::MachineConfiguration.find(profile.id, context).cpu
+    else
+      cpu_override[1]
+    end
+  end
+
+  def self.convert_instance_memory(profile, context)
+    machine_conf = CIMI::Model::MachineConfiguration.find(profile.name, context)
+    memory_override = profile.overrides.find { |p, v| p == :memory }
+    {
+      :quantity => memory_override.nil? ? machine_conf.memory[:quantity] : memory_override[1],
+      :units => machine_conf.memory[:units]
+    }
+  end
+
+  def self.convert_instance_storage(profile, context)
+    machine_conf = CIMI::Model::MachineConfiguration.find(profile.name, context)
+    storage_override = profile.overrides.find { |p, v| p == :storage }
+    [
+      { :capacity => {
+          :quantity => storage_override.nil? ? machine_conf.disks.first[:capacity][:quantity] : storage_override[1],
+          :units => machine_conf.disks.first[:capacity][:units]
+        }
+      }
+    ]
+  end
+
+  def self.convert_instance_addresses(instance)
+    (instance.public_addresses + instance.private_addresses).collect do |address|
+      {
+        :hostname => address.is_hostname? ? address : nil,
+        :mac_address => address.is_mac? ? address : nil,
+        :state => 'Active',
+        :protocol => 'IPv4',
+        :address => address.is_ipv4? ? address : nil,
+        :allocation => 'Static'
+      }
+    end
+  end
+
+  def self.convert_instance_actions(instance, context)
+    instance.actions.collect do |action|
+      action = :destroy if action == :delete # In CIMI destroy operation become delete
+      action = :restart if action == :reboot  # In CIMI reboot operation become restart
+      { :href => context.send(:"#{action}_machine_url", instance.id), :rel => "http://www.dmtf.org/cimi/action/#{action}" }
+    end
+  end
+
+  def self.convert_storage_volumes(instance, context)
+    instance.storage_volumes ||= [] #deal with nilpointers
+    instance.storage_volumes.map{|vol| {:href=>context.volume_url(vol.keys.first),
+                                       :attachment_point=>vol.values.first} }
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_admin.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_admin.rb b/server/lib/cimi/models/machine_admin.rb
new file mode 100644
index 0000000..fed7c80
--- /dev/null
+++ b/server/lib/cimi/models/machine_admin.rb
@@ -0,0 +1,59 @@
+# 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::MachineAdmin < CIMI::Model::Base
+
+  text :username
+  text :password
+  text :key
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id == :all
+      keys = context.driver.keys(context.credentials)
+      keys.map { |key| from_key(key, context) }
+    else
+      key = context.driver.key(context.credentials, :id => id)
+      from_key(key, context)
+    end
+  end
+
+  def self.create_from_xml(body, context)
+    machine_admin = MachineAdmin.from_xml(body)
+    key = context.driver.create_key(context.credentials, :key_name => machine_admin.name)
+    from_key(key, context)
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_key(context.credentials, :id => id)
+  end
+
+  private
+
+  def self.from_key(key, context)
+    self.new(
+      :name => key.id,
+      :username => key.username,
+      :password => key.is_password? ? key.password : key.fingerprint,
+      :key => key.is_key? ? key.pem_rsa_key : nil,
+      :id => context.machine_admin_url(key.id),
+      :created => Time.now
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_admin_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_admin_collection.rb b/server/lib/cimi/models/machine_admin_collection.rb
new file mode 100644
index 0000000..08c1559
--- /dev/null
+++ b/server/lib/cimi/models/machine_admin_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineAdminCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine_admin
+
+  array :machine_admins do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machine_admins_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineAdminCollection",
+      :machine_admins => CIMI::Model::MachineAdmin.all_uri(context)
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_collection.rb b/server/lib/cimi/models/machine_collection.rb
new file mode 100644
index 0000000..9154aa9
--- /dev/null
+++ b/server/lib/cimi/models/machine_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine
+
+  array :machines do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machines_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineCollection",
+      :machines => CIMI::Model::Machine.all_uri(context)
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_configuration.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_configuration.rb b/server/lib/cimi/models/machine_configuration.rb
new file mode 100644
index 0000000..f9d98f2
--- /dev/null
+++ b/server/lib/cimi/models/machine_configuration.rb
@@ -0,0 +1,70 @@
+# 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::MachineConfiguration < CIMI::Model::Base
+
+  struct :memory do
+    scalar :quantity
+    scalar :units
+  end
+
+  text :cpu
+
+  array :disks do
+    struct :capacity do
+      scalar :quantity
+      scalar :units
+    end
+    scalar :format
+    scalar :attachment_point
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    profiles = []
+    if id == :all
+      profiles = context.driver.hardware_profiles(context.credentials)
+      profiles.map { |profile| from_hardware_profile(profile, context) }.compact
+    else
+      profile = context.driver.hardware_profile(context.credentials, id)
+      from_hardware_profile(profile, context)
+    end
+  end
+
+  private
+
+  def self.from_hardware_profile(profile, context)
+    # We accept just profiles with all properties set
+    return unless profile.memory or profile.cpu or profile.storage
+    memory = profile.memory.value || profile.memory.default
+    cpu = profile.cpu.value || profile.cpu.default
+    storage = profile.storage.value || profile.storage.default
+    machine_hash = {
+      :name => profile.name,
+      :description => "Machine Configuration with #{memory} #{profile.memory.unit} "+
+        "of memory and #{cpu} CPU",
+      :cpu => cpu,
+      :created => Time.now.to_s,  # FIXME: DC hardware_profile has no mention about created_at
+      :memory => { :quantity => profile.memory.value || profile.memory.default, :units => profile.memory.unit },
+      :disks => [ { :capacity => { :quantity => profile.storage.value || profile.storage.default, :units => profile.storage.unit } } ],
+      :id => context.machine_configuration_url(profile.name)
+    }
+    self.new(machine_hash)
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_configuration_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_configuration_collection.rb b/server/lib/cimi/models/machine_configuration_collection.rb
new file mode 100644
index 0000000..6d7ebad
--- /dev/null
+++ b/server/lib/cimi/models/machine_configuration_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineConfigurationCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine_configuration
+
+  array :machine_configurations do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machine_configurations_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineConfigurationCollection",
+      :machine_configurations => CIMI::Model::MachineConfiguration.all_uri(context)
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_image.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_image.rb b/server/lib/cimi/models/machine_image.rb
new file mode 100644
index 0000000..7389475
--- /dev/null
+++ b/server/lib/cimi/models/machine_image.rb
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineImage < CIMI::Model::Base
+
+  href :image_location
+  text :image_data
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    images = []
+    if id == :all
+      images = context.driver.images(context.credentials)
+      images.map { |image| from_image(image, context) }
+    else
+      image = context.driver.image(context.credentials, :id => id)
+      from_image(image, context)
+    end
+  end
+
+  def self.from_image(image, context)
+    self.new(
+      :name => image.id,
+      :id => context.machine_image_url(image.id),
+      :description => image.description,
+      :created => Time.now.to_s,
+      :image_location => { :href => "#{context.driver.name}://#{image.id}" } # FIXME
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_image_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_image_collection.rb b/server/lib/cimi/models/machine_image_collection.rb
new file mode 100644
index 0000000..70bdc7b
--- /dev/null
+++ b/server/lib/cimi/models/machine_image_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineImageCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine_image
+
+  array :machine_images do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machine_images_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineImageCollection",
+      :machine_images => CIMI::Model::MachineImage.all_uri(context)
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_template.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_template.rb b/server/lib/cimi/models/machine_template.rb
new file mode 100644
index 0000000..8a88052
--- /dev/null
+++ b/server/lib/cimi/models/machine_template.rb
@@ -0,0 +1,41 @@
+# 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::MachineTemplate < CIMI::Model::Base
+
+  href :machine_config
+  href :machine_image
+  href :machine_admin
+
+  array :volumes do
+    scalar :href
+    scalar :protocol
+    scalar :attachment_point
+  end
+
+  array :volume_templates do
+    scalar :href, :attachment_point, :protocol
+  end
+
+  array :network_interfaces do
+    href :vsp
+    text :hostname, :mac_address, :state, :protocol, :allocation
+    text :address, :default_gateway, :dns, :max_transmission_unit
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/machine_template_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/machine_template_collection.rb b/server/lib/cimi/models/machine_template_collection.rb
new file mode 100644
index 0000000..d2a3f23
--- /dev/null
+++ b/server/lib/cimi/models/machine_template_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::MachineTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :machine_template
+
+  array :machine_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.machine_template_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} MachineTemplateCollection",
+      :machine_templates => CIMI::Model::MachineTemplate.all_uri(context)
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/network.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/network.rb b/server/lib/cimi/models/network.rb
new file mode 100644
index 0000000..3d9c7ed
--- /dev/null
+++ b/server/lib/cimi/models/network.rb
@@ -0,0 +1,109 @@
+# 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::Network < CIMI::Model::Base
+
+  text :state
+
+  text :access
+
+  text :bandwidth_limit
+
+  text :traffic_priority
+
+  text :max_traffic_delay
+
+  text :max_traffic_loss
+
+  text :max_traffic_jitter
+
+  href :routing_group
+
+  href :event_log
+
+  array :meters do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    networks=[]
+    if id==:all
+      networks = context.driver.networks(context.credentials, {:env=>context})
+    else
+      networks = context.driver.networks(context.credentials, {:id=>id, :env=>context})
+    end
+    networks
+  end
+
+  def self.create(request_body, context, type)
+    input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false,"NormaliseSpace"=>2}) : JSON.parse(request_body)
+    if input["networkTemplate"]["href"] #template by reference
+      network_config, routing_group = get_by_reference(input, context)
+    else
+      if input["networkTemplate"]["networkConfig"]["href"] # configuration by reference
+        network_config = CIMI::Model::NetworkConfiguration.find(context.href_id(input["networkTemplate"]["networkConfig"]["href"],
+                                                                                :network_configurations), context)
+      else #configuration by value
+        network_config = get_by_value(request_body, type)
+      end
+      routing_group = CIMI::Model::RoutingGroup.find(context.href_id(input["networkTemplate"]["routingGroup"]["href"],
+                                                                     :routing_groups), context)
+    end
+    params = {:network_config => network_config, :routing_group => routing_group, :name=>input["name"],
+              :description=>input["description"], :env=>context}
+    raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}")  if params.has_value?(nil)
+    context.driver.create_network(context.credentials, params)
+  end
+
+  def self.delete!(id, context)
+    context.driver.delete_network(context.credentials, id)
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_network", context.credentials, self.name)
+        block.callback :success
+      else
+        raise "Operation #{action.name} failed to execute on the Network #{self.name} "
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+  private
+
+  def self.get_by_reference(input, context)
+    network_template = CIMI::Model::NetworkTemplate.find(context.href_id(input["networkTemplate"]["href"], :network_templates), context)
+    network_config = CIMI::Model::NetworkConfiguration.find(context.href_id(network_template.network_config.href, :network_configurations), context)
+    routing_group = CIMI::Model::RoutingGroup.find(context.href_id(network_template.routing_group.href, :routing_groups), context)
+    return network_config, routing_group
+  end
+
+  def self.get_by_value(request_body, type)
+    if type == :xml
+      xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
+      network_config = CIMI::Model::NetworkConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["networkTemplate"][0]["networkConfig"][0]))
+    else
+     json = JSON.parse(request_body)
+      network_config = CIMI::Model::NetworkConfiguration.from_json(JSON.generate(json["networkTemplate"]["networkConfig"]))
+    end
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/network_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/network_collection.rb b/server/lib/cimi/models/network_collection.rb
new file mode 100644
index 0000000..d76a3dd
--- /dev/null
+++ b/server/lib/cimi/models/network_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::NetworkCollection < CIMI::Model::Base
+
+  act_as_root_entity :network
+
+  array :networks do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.networks_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} NetworkCollection",
+      :networks => CIMI::Model::Network.all(context).map { |c| { :href => c.id } }
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/network_configuration.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/network_configuration.rb b/server/lib/cimi/models/network_configuration.rb
new file mode 100644
index 0000000..1b04548
--- /dev/null
+++ b/server/lib/cimi/models/network_configuration.rb
@@ -0,0 +1,49 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::NetworkConfiguration < CIMI::Model::Base
+
+  text :access
+
+  text :bandwidth_limit
+
+  text :traffic_priority
+
+  text :max_traffic_delay
+
+  text :max_traffic_loss
+
+  text :max_traffic_jitter
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    network_configs = []
+    if id==:all
+      network_configs = context.driver.network_configurations(context.credentials, {:env=>context})
+    else
+      network_configs = context.driver.network_configurations(context.credentials, {:env=>context, :id=>id})
+    end
+    network_configs
+  end
+
+  def self.create_from_xml(request_body, context)
+  end
+
+  def self.create_from_json(request_body, context)
+  end
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/network_configuration_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/network_configuration_collection.rb b/server/lib/cimi/models/network_configuration_collection.rb
new file mode 100644
index 0000000..fc14592
--- /dev/null
+++ b/server/lib/cimi/models/network_configuration_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::NetworkConfigurationCollection < CIMI::Model::Base
+
+  act_as_root_entity :network_configuration
+
+  array :network_configurations do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.network_configurations_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} NetworkConfigurationCollection",
+      :network_configurations => CIMI::Model::NetworkConfiguration.all(context).map { |c| { :href => c.id } }
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/network_template.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/network_template.rb b/server/lib/cimi/models/network_template.rb
new file mode 100644
index 0000000..ce3b990
--- /dev/null
+++ b/server/lib/cimi/models/network_template.rb
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::NetworkTemplate < CIMI::Model::Base
+
+  href :network_config
+
+  href :routing_group
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    network_templates = []
+    if id==:all
+      network_templates = context.driver.network_templates(context.credentials, {:env=>context})
+    else
+      network_templates = context.driver.network_templates(context.credentials, {:env=>context, :id=>id})
+    end
+    network_templates
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/network_template_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/network_template_collection.rb b/server/lib/cimi/models/network_template_collection.rb
new file mode 100644
index 0000000..b2ac537
--- /dev/null
+++ b/server/lib/cimi/models/network_template_collection.rb
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+class CIMI::Model::NetworkTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :network_template
+
+  array :network_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.network_templates_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} NetworkTemplateCollection",
+      :network_templates => CIMI::Model::NetworkTemplate.all_uri(context)
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/routing_group.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/routing_group.rb b/server/lib/cimi/models/routing_group.rb
new file mode 100644
index 0000000..d26f4d7
--- /dev/null
+++ b/server/lib/cimi/models/routing_group.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::RoutingGroup < CIMI::Model::Base
+
+  array :networks do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.routing_groups(context.credentials, {:env=>context})
+    else
+      context.driver.routing_groups(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/routing_group_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/routing_group_collection.rb b/server/lib/cimi/models/routing_group_collection.rb
new file mode 100644
index 0000000..285e164
--- /dev/null
+++ b/server/lib/cimi/models/routing_group_collection.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::RoutingGroupCollection < CIMI::Model::Base
+
+  act_as_root_entity :routing_group
+
+  array :routing_groups do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.routing_groups_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} RoutingGroupCollection",
+      :routing_groups => CIMI::Model::RoutingGroup.all_uri(context)
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/routing_group_template.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/routing_group_template.rb b/server/lib/cimi/models/routing_group_template.rb
new file mode 100644
index 0000000..204a353
--- /dev/null
+++ b/server/lib/cimi/models/routing_group_template.rb
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::RoutingGroupTemplate < CIMI::Model::Base
+
+  array :networks do
+    scalar :href
+  end
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    if id==:all
+      context.driver.routing_group_templates(context.credentials, {:env=>context})
+    else
+      context.driver.routing_group_templates(context.credentials, {:env=>context, :id=>id})
+    end
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/routing_group_template_collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/routing_group_template_collection.rb b/server/lib/cimi/models/routing_group_template_collection.rb
new file mode 100644
index 0000000..61a4a68
--- /dev/null
+++ b/server/lib/cimi/models/routing_group_template_collection.rb
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+class CIMI::Model::RoutingGroupTemplateCollection < CIMI::Model::Base
+
+  act_as_root_entity :routing_group_template
+
+  array :routing_group_templates do
+    scalar :href
+  end
+
+  def self.default(context)
+    self.new(
+      :id => context.routing_group_templates_url,
+      :name => 'default',
+      :created => Time.now,
+      :description => "#{context.driver.name.capitalize} RoutingGroupTemplateCollection",
+      :routing_group_templates => CIMI::Model::RoutingGroupTemplate.all_uri(context)
+    )
+  end
+
+end

http://git-wip-us.apache.org/repos/asf/deltacloud/blob/a8a53bc6/server/lib/cimi/models/schema.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
new file mode 100644
index 0000000..f301b69
--- /dev/null
+++ b/server/lib/cimi/models/schema.rb
@@ -0,0 +1,277 @@
+# 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.
+#
+
+# The smarts of converting from XML and JSON into internal objects
+class CIMI::Model::Schema
+
+  #
+  # Attributes describe how we extract values from XML/JSON
+  #
+  class Attribute
+    attr_reader :name, :xml_name, :json_name
+
+    def initialize(name, opts = {})
+      @name = name
+      @xml_name = (opts[:xml_name] || name).to_s.camelize(true)
+      @json_name = (opts[:json_name] || name).to_s.camelize(true)
+    end
+
+    def from_xml(xml, model)
+      model[@name] = xml[@xml_name].first if xml.has_key?(@xml_name)
+    end
+
+    def from_json(json, model)
+      model[@name] = json[@json_name]
+    end
+
+    def to_xml(model, xml)
+      xml[@xml_name] = [model[@name]] if model[@name]
+    end
+
+    def to_json(model, json)
+      json[@json_name] = model[@name] if model and model[@name]
+    end
+  end
+
+  class Scalar < Attribute
+    def initialize(name, opts)
+      @text = opts[:text]
+      if ! [nil, :nested, :direct].include?(@text)
+        raise "text option for scalar must be :nested or :direct"
+      end
+      super(name, opts)
+    end
+
+    def text?; @text; end
+
+    def nested_text?; @text == :nested; end
+
+    def from_xml(xml, model)
+      case @text
+        when :nested then model[@name] = xml[@xml_name].first["content"] if xml[@xml_name]
+        when :direct then model[@name] = xml["content"]
+        else model[@name] = xml[@xml_name]
+      end
+    end
+
+    def to_xml(model, xml)
+      return unless model
+      return unless model[@name]
+      case @text
+        when :nested then xml[@xml_name] = [{ "content" => model[@name] }]
+        when :direct then xml["content"] = model[@name]
+        else xml[@xml_name] = model[@name]
+      end
+    end
+  end
+
+  class Struct < Attribute
+    def initialize(name, opts, &block)
+      content = opts[:content]
+      super(name, opts)
+      @schema = CIMI::Model::Schema.new
+      @schema.instance_eval(&block) if block_given?
+      @schema.scalar(content, :text => :direct) if content
+    end
+
+    def from_xml(xml, model)
+      xml = xml.has_key?(xml_name) ? xml[xml_name].first : {}
+      model[name] = convert_from_xml(xml)
+    end
+
+    def from_json(json, model)
+      json = json.has_key?(json_name) ? json[json_name] : {}
+      model[name] = convert_from_json(json)
+    end
+
+    def to_xml(model, xml)
+      conv = convert_to_xml(model[name])
+      xml[xml_name] = [conv] unless conv.empty?
+    end
+
+    def to_json(model, json)
+      conv = convert_to_json(model[name])
+      json[json_name] = conv unless conv.empty?
+    end
+
+    def convert_from_xml(xml)
+      sub = struct.new
+      @schema.from_xml(xml, sub)
+      sub
+    end
+
+    def convert_from_json(json)
+      sub = struct.new
+      @schema.from_json(json, sub)
+      sub
+    end
+
+    def convert_to_xml(model)
+      xml = {}
+      @schema.to_xml(model, xml)
+      xml
+    end
+
+    def convert_to_json(model)
+      json = {}
+      @schema.to_json(model, json)
+      json
+    end
+
+    private
+    def struct
+      cname = "CIMI_#{json_name.upcase_first}"
+      if ::Struct.const_defined?(cname)
+        ::Struct.const_get(cname)
+      else
+        ::Struct.new("CIMI_#{json_name.upcase_first}",
+                     *@schema.attribute_names)
+      end
+    end
+  end
+
+  class Array < Attribute
+    # For an array :things, we collect all <thing/> elements (XmlSimple
+    # actually does the collecting)
+    def initialize(name, opts = {}, &block)
+      opts[:xml_name] = name.to_s.singularize unless opts[:xml_name]
+      super(name, opts)
+      @struct = Struct.new(name, opts, &block)
+    end
+
+    def from_xml(xml, model)
+      model[name] = (xml[xml_name] || []).map { |elt| @struct.convert_from_xml(elt) }
+    end
+
+    def from_json(json, model)
+      model[name] = (json[json_name] || []).map { |elt| @struct.convert_from_json(elt) }
+    end
+
+    def to_xml(model, xml)
+      ary = (model[name] || []).map { |elt| @struct.convert_to_xml(elt) }
+      xml[xml_name] = ary unless ary.empty?
+    end
+
+    def to_json(model, json)
+      ary = (model[name] || []).map { |elt| @struct.convert_to_json(elt) }
+      json[json_name] = ary unless ary.empty?
+    end
+  end
+
+  class Hash < Attribute
+
+    def initialize(name, opts = {}, &block)
+      opts[:json_name] = name.to_s.pluralize unless opts[:json_name]
+      super(name, opts)
+      @struct = Struct.new(name, opts, &block)
+    end
+
+    def from_xml(xml, model)
+      model[name] = (xml[xml_name] || []).map { |elt| @struct.convert_from_xml(elt) }
+    end
+
+    def from_json(json, model)
+      model[name] = (json[json_name] || {}).inject([]) do |result,item|
+        result << @struct.convert_from_json({ 'name' => item[0], 'value' => item[1] })
+      end
+    end
+
+    def to_xml(model, xml)
+      ary = (model[name] || []).map { |elt| @struct.convert_to_xml(elt) }
+      xml[xml_name] = ary unless ary.empty?
+    end
+
+    def to_json(model, json)
+      ary = (model[name] || []).map { |elt| @struct.convert_to_json(elt) }
+      json[json_name] = ary.inject({}) { |result, item| result[item['name']] = item['value']; result } unless ary.empty?
+    end
+  end
+
+  #
+  # The actual Schema class
+  #
+  def initialize
+    @attributes = []
+  end
+
+  def from_xml(xml, model = {})
+    @attributes.freeze
+    @attributes.each { |attr| attr.from_xml(xml, model) }
+    model
+  end
+
+  def from_json(json, model = {})
+    @attributes.freeze
+    @attributes.each { |attr| attr.from_json(json, model) }
+    model
+  end
+
+  def to_xml(model, xml = {})
+    @attributes.freeze
+    @attributes.each { |attr| attr.to_xml(model, xml) }
+    xml
+  end
+
+  def to_json(model, json = {})
+    @attributes.freeze
+    @attributes.each { |attr| attr.to_json(model, json) }
+    json
+  end
+
+  def attribute_names
+    @attributes.map { |a| a.name }
+  end
+
+  #
+  # The DSL
+  #
+  # Requires that the class into which this is included has a
+  # +add_attributes!+ method
+  module DSL
+    def href(*args)
+      args.each { |arg| struct(arg) { scalar :href } }
+    end
+
+    def text(*args)
+      args.expand_opts!(:text => :nested)
+      scalar(*args)
+    end
+
+    def scalar(*args)
+      add_attributes!(args, Scalar)
+    end
+
+    def array(name, opts={}, &block)
+      add_attributes!([name, opts], Array, &block)
+    end
+
+    def struct(name, opts={}, &block)
+      add_attributes!([name, opts], Struct, &block)
+    end
+
+    def hash(name, opts={}, &block)
+      add_attributes!([name, opts], Hash, &block)
+    end
+  end
+
+  include DSL
+
+  def add_attributes!(args, attr_klass, &block)
+    raise "The schema has already been used to convert objects" if @attributes.frozen?
+    opts = args.extract_opts!
+    args.each { |arg| @attributes << attr_klass.new(arg, opts, &block) }
+  end
+end


Mime
View raw message