You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by mf...@redhat.com on 2012/04/17 15:39:41 UTC

[PATCH core 02/32] Core: Added collections directory with Rabbit collections

From: Michal Fojtik <mf...@redhat.com>


Signed-off-by: Michal fojtik <mf...@redhat.com>
---
 server/lib/deltacloud/collections/addresses.rb     |   83 ++++++++
 server/lib/deltacloud/collections/buckets.rb       |  215 ++++++++++++++++++++
 server/lib/deltacloud/collections/drivers.rb       |   51 +++++
 server/lib/deltacloud/collections/firewalls.rb     |  116 +++++++++++
 .../deltacloud/collections/hardware_profiles.rb    |   27 +++
 server/lib/deltacloud/collections/images.rb        |   70 +++++++
 .../lib/deltacloud/collections/instance_states.rb  |   57 ++++++
 server/lib/deltacloud/collections/instances.rb     |  103 ++++++++++
 server/lib/deltacloud/collections/keys.rb          |   61 ++++++
 .../lib/deltacloud/collections/load_balancers.rb   |   85 ++++++++
 server/lib/deltacloud/collections/realms.rb        |   27 +++
 .../deltacloud/collections/storage_snapshots.rb    |   51 +++++
 .../lib/deltacloud/collections/storage_volumes.rb  |   99 +++++++++
 13 files changed, 1045 insertions(+)
 create mode 100644 server/lib/deltacloud/collections/addresses.rb
 create mode 100644 server/lib/deltacloud/collections/buckets.rb
 create mode 100644 server/lib/deltacloud/collections/drivers.rb
 create mode 100644 server/lib/deltacloud/collections/firewalls.rb
 create mode 100644 server/lib/deltacloud/collections/hardware_profiles.rb
 create mode 100644 server/lib/deltacloud/collections/images.rb
 create mode 100644 server/lib/deltacloud/collections/instance_states.rb
 create mode 100644 server/lib/deltacloud/collections/instances.rb
 create mode 100644 server/lib/deltacloud/collections/keys.rb
 create mode 100644 server/lib/deltacloud/collections/load_balancers.rb
 create mode 100644 server/lib/deltacloud/collections/realms.rb
 create mode 100644 server/lib/deltacloud/collections/storage_snapshots.rb
 create mode 100644 server/lib/deltacloud/collections/storage_volumes.rb

diff --git a/server/lib/deltacloud/collections/addresses.rb b/server/lib/deltacloud/collections/addresses.rb
new file mode 100644
index 0000000..b97d170
--- /dev/null
+++ b/server/lib/deltacloud/collections/addresses.rb
@@ -0,0 +1,83 @@
+# 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 Deltacloud::Collections
+  class Addresses < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+
+    collection :addresses do
+      description "Pool of IP addresses allocated in cloud provider"
+
+      standard_index_operation
+      standard_show_operation
+
+      operation :create, :with_capability => :create_address do
+        description "Acquire a new IP address for use with your account."
+        control do
+          @address = driver.create_address(credentials, {})
+          status 201    # Created
+          response['Location'] = address_url(@address.id)
+          respond_to do |format|
+            format.xml  { haml :"addresses/show", :ugly => true }
+            format.html { haml :"addresses/_address", :layout => false }
+            format.json { convert_to_json(:address, @address) }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_address do
+        control do
+          driver.destroy_address(credentials, { :id => params[:id]})
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(addresses_url) }
+          end
+        end
+      end
+
+      action :associate, :with_capability => :associate_address do
+        description "Associate an IP address to an instance"
+        param :instance_id, :string, :required
+        control do
+          driver.associate_address(credentials, { :id => params[:id], :instance_id => params[:instance_id]})
+          status 202   # Accepted
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(address_url(params[:id])) }
+          end
+        end
+      end
+
+      action :disassociate, :with_capability => :associate_address do
+        description "Disassociate an IP address from an instance"
+        control do
+          driver.disassociate_address(credentials, { :id => params[:id] })
+          status 202   # Accepted
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(address_url(params[:id])) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/buckets.rb b/server/lib/deltacloud/collections/buckets.rb
new file mode 100644
index 0000000..044bd6a
--- /dev/null
+++ b/server/lib/deltacloud/collections/buckets.rb
@@ -0,0 +1,215 @@
+# 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 Deltacloud::Collections
+  class Buckets < Base
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    collection :buckets do
+
+      collection :blobs, :with_id => :blob_id, :no_member => true do
+
+        operation :show, :with_capability => :blob do
+          control do
+            @blob = driver.blob(credentials, { :id => params[:blob_id], 'bucket' => params[:id]} )
+            if @blob
+              respond_to do |format|
+                format.xml { haml :"blobs/show" }
+                format.html { haml :"blobs/show" }
+                format.json { convert_to_json(:blob, @blob) }
+              end
+            else
+              report_error(404)
+            end
+          end
+
+        end
+
+        operation :create, :with_capability => :create_blob do
+          description "Create new blob"
+          param :blob_id,  :string,  :required
+          param :blob_data, :hash, :required
+          control do
+            bucket_id = params[:id]
+            blob_id = params['blob_id']
+            blob_data = params['blob_data']
+            user_meta = {}
+            #metadata from params (i.e., passed by http form post, e.g. browser)
+            max = params[:meta_params]
+            if(max)
+              (1..max.to_i).each do |i|
+                key = params[:"meta_name#{i}"]
+                key = "HTTP_X_Deltacloud_Blobmeta_#{key}"
+                value = params[:"meta_value#{i}"]
+                user_meta[key] = value
+              end
+            end
+            @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
+            respond_to do |format|
+              format.xml { haml :"blobs/show" }
+              format.html { haml :"blobs/show"}
+              format.json {convert_to_json(:blob, @blob)}
+            end
+          end
+        end
+
+        operation :destroy, :with_capability => :delete_blob do
+          control do
+            bucket_id = params[:id]
+            blob_id = params[:blob_id]
+            driver.delete_blob(credentials, bucket_id, blob_id)
+            status 204
+            respond_to do |format|
+              format.xml
+              format.json
+              format.html { redirect(bucket_url(bucket_id)) }
+            end
+          end
+        end
+
+        action :stream, :http_method => :put, :with_capability => :create_blob do
+          description "Stream new blob data into the blob"
+          control do
+            if(env["BLOB_SUCCESS"]) #ie got a 200ok after putting blob
+              content_type = env["CONTENT_TYPE"]
+              content_type ||=  ""
+              @blob = driver.blob(credentials, {:id => params[:blob],
+                                                'bucket' => params[:bucket]})
+              respond_to do |format|
+                format.xml { haml :"blobs/show" }
+                format.html { haml :"blobs/show" }
+                format.json { convert_to_json(:blob, @blob) }
+              end
+            elsif(env["BLOB_FAIL"])
+              report_error(500) #OK?
+            else # small blobs - < 112kb dont hit the streaming monkey patch - use 'normal' create_blob
+              # also, if running under webrick don't hit the streaming patch (Thin specific)
+              bucket_id = params[:bucket]
+              blob_id = params[:blob]
+              temp_file = Tempfile.new("temp_blob_file")
+              temp_file.write(env['rack.input'].read)
+              temp_file.flush
+              content_type = env['CONTENT_TYPE'] || ""
+              blob_data = {:tempfile => temp_file, :type => content_type}
+              user_meta = BlobHelper::extract_blob_metadata_hash(request.env)
+              @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
+              temp_file.delete
+              respond_to do |format|
+                format.xml { haml :"blobs/show" }
+                format.html { haml :"blobs/show" }
+                format.json { convert_to_json(:blob, @blob) }
+              end
+            end
+          end
+        end
+
+        action :metadata, :http_method => :head, :with_capability => :blob_metadata do
+          control do
+            @blob_id = params[:blob]
+            @blob_metadata = driver.blob_metadata(credentials, {:id => params[:blob], 'bucket' => params[:bucket]})
+            if @blob_metadata
+              @blob_metadata.each do |k,v|
+                headers["X-Deltacloud-Blobmeta-#{k}"] = v
+              end
+              status 204
+              respond_to do |format|
+                format.xml
+                format.json
+              end
+            else
+              report_error(404)
+            end
+          end
+        end
+
+        action :update, :http_method => :post, :with_capability => :update_blob_metadata do
+          control do
+            meta_hash = BlobHelper::extract_blob_metadata_hash(request.env)
+            success = driver.update_blob_metadata(credentials, {'bucket'=>params[:bucket], :id =>params[:blob], 'meta_hash' => meta_hash})
+            if(success)
+              meta_hash.each do |k,v|
+                headers["X-Deltacloud-Blobmeta-#{k}"] = v
+              end
+              status 204
+              respond_to do |format|
+                format.xml
+                format.json
+              end
+            else
+              report_error(404) #FIXME is this the right error code?
+            end
+          end
+        end
+
+        action :content, :http_method => :get, :with_capability => :blob do
+          description "Download blob content"
+          control do
+            @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
+            if @blob
+              params['content_length'] = @blob.content_length
+              params['content_type'] = @blob.content_type
+              params['content_disposition'] = "attachment; filename=#{@blob.id}"
+              BlobStream.call(env, credentials, params)
+            else
+              report_error(404)
+            end
+          end
+        end
+
+      end
+
+      get route_for('/buckets/new') do
+        respond_to do |format|
+          format.html { haml :"buckets/new" }
+        end
+      end
+
+      standard_show_operation
+      standard_index_operation
+
+      operation :create, :with_capability => :create_bucket do
+        param :name,      :string,    :required
+        control do
+          @bucket = driver.create_bucket(credentials, params[:name], params)
+          status 201
+          response['Location'] = bucket_url(@bucket.id)
+          respond_to do |format|
+            format.xml  { haml :"buckets/show" }
+            format.json { convert_to_json(:bucket, @bucket) }
+            format.html do
+              redirect bucket_url(@bucket.id) if @bucket and @bucket.id
+              redirect buckets_url
+            end
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :delete_bucket do
+        control do
+          driver.delete_bucket(credentials, params[:id], params)
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html {  redirect(buckets_url) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/drivers.rb b/server/lib/deltacloud/collections/drivers.rb
new file mode 100644
index 0000000..41f324a
--- /dev/null
+++ b/server/lib/deltacloud/collections/drivers.rb
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Drivers < Base
+
+    collection :drivers do
+
+      operation :index do
+        control do
+          @drivers = Deltacloud::Drivers.driver_config
+          respond_to do |format|
+            format.xml { haml :"drivers/index" }
+            format.json { @drivers.to_json }
+            format.html { haml :"drivers/index" }
+          end 
+        end
+      end
+
+      operation :show do
+        control do
+          @name = params[:id].to_sym
+          if driver_symbol == @name
+            @providers = driver.providers(credentials)  if driver.respond_to? :providers
+          end
+          @driver = Deltacloud::Drivers.driver_config[@name]
+          halt 404 unless @driver
+          respond_to do |format|
+            format.xml { haml :"drivers/show" }
+            format.json { @driver.to_json }
+            format.html { haml :"drivers/show" }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/firewalls.rb b/server/lib/deltacloud/collections/firewalls.rb
new file mode 100644
index 0000000..0a4242a
--- /dev/null
+++ b/server/lib/deltacloud/collections/firewalls.rb
@@ -0,0 +1,116 @@
+# 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 Deltacloud::Collections
+  class Firewalls < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    get route_for('/firewalls/:id/new_rule') do
+      @firewall_name = params[:id]
+      respond_to do |format|
+        format.html {haml :"firewalls/new_rule" }
+      end
+    end
+
+    new_route_for :firewalls
+
+    collection :firewalls do
+      description "Allow user to define firewall rules for an instance (ec2 security groups) eg expose ssh access [port 22, tcp]."
+
+      collection :rules, :with_id => :rule_id, :no_member => true do
+
+        operation :destroy, :with_capability => :delete_firewall_rule do
+          control do
+            opts = {}
+            opts[:firewall] = params[:id]
+            opts[:rule_id] = params[:rule_id]
+            driver.delete_firewall_rule(credentials, opts)
+            status 204
+            respond_to do |format|
+              format.xml
+              format.json
+              format.html {redirect firewall_url(params[:id])}
+            end
+          end
+        end
+
+      end
+
+      standard_show_operation
+      standard_index_operation
+
+      operation :create, :with_capability => :create_firewall do
+        param :name,          :string,    :required
+        param :description,   :string,    :required
+        control do
+          @firewall = driver.create_firewall(credentials, params )
+          status 201  # Created
+          response['Location'] = firewall_url(@firewall.id)
+          respond_to do |format|
+            format.xml  { haml :"firewalls/show" }
+            format.html { haml :"firewalls/show" }
+            format.json { convert_to_json(:firewall, @firewall) }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :delete_firewall do
+        control do
+          driver.delete_firewall(credentials, params)
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html {  redirect(firewalls_url) }
+          end
+        end
+      end
+
+      action :rules, :with_capability => :create_firewall_rule do
+        param :protocol,  :required, :string, ['tcp','udp','icmp'], "Transport layer protocol for the rule"
+        param :port_from, :required, :string, [], "Start of port range for the rule"
+        param :port_to,   :required, :string, [], "End of port range for the rule"
+        control do
+          #source IPs from params
+          addresses =  params.inject([]){|result,current| result << current.last unless current.grep(/^ip[-_]address/i).empty?; result}
+          #source groups from params
+          groups = {}
+          max_groups  = params.select{|k,v| k=~/^group/}.size/2
+          for i in (1..max_groups) do
+            groups.merge!({params["group#{i}"]=>params["group#{i}owner"]})
+          end
+          params['addresses'] = addresses
+          params['groups'] = groups
+          if addresses.empty? && groups.empty?
+            raise Deltacloud::ExceptionHandler::ValidationFailure.new(
+              StandardError.new("No sources. Specify at least one source ip_address or group")
+            )
+          end
+          driver.create_firewall_rule(credentials, params)
+          @firewall = driver.firewall(credentials, {:id => params[:id]})
+          status 201
+          respond_to do |format|
+            format.xml  { haml :"firewalls/show" }
+            format.html { haml :"firewalls/show" }
+            format.json { convert_to_json(:firewall, @firewall) }
+          end
+        end
+      end
+
+    end
+  end
+end
diff --git a/server/lib/deltacloud/collections/hardware_profiles.rb b/server/lib/deltacloud/collections/hardware_profiles.rb
new file mode 100644
index 0000000..ff01d4a
--- /dev/null
+++ b/server/lib/deltacloud/collections/hardware_profiles.rb
@@ -0,0 +1,27 @@
+# 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 Deltacloud::Collections
+  class HardwareProfiles < Base
+
+    collection :hardware_profiles do
+
+      standard_index_operation
+      standard_show_operation
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/images.rb b/server/lib/deltacloud/collections/images.rb
new file mode 100644
index 0000000..c8b3e08
--- /dev/null
+++ b/server/lib/deltacloud/collections/images.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.
+
+module Deltacloud::Collections
+  class Images < Base
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    new_route_for :images do
+      @instance = Instance.new( :id => params[:instance_id] )
+      status 404 unless @instance
+    end
+
+    collection :images do
+      description "Within a cloud provider a realm represents a boundary containing resources"
+
+      operation :index, :with_capability => :images do
+        param :architecture,  :string,  :optional
+        control { filter_all(:images) }
+      end
+
+      operation :show, :with_capability => :image do
+        control { show(:image) }
+      end
+
+      operation :create, :with_capability => :create_image do
+        param :instance_id, :string, :required
+        control do
+          @image = driver.create_image(credentials, {
+            :id => params[:instance_id],
+            :name => params[:name],
+            :description => params[:description]
+          })
+          status 201  # Created
+          response['Location'] = image_url(@image.id)
+          respond_to do |format|
+            format.xml  { haml :"images/show" }
+            format.json { xml_to_json('images/show') }
+            format.html { haml :"images/show" }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_image do
+        control do
+          driver.destroy_image(credentials, params[:id])
+          respond_to do |format|
+            format.xml { status 204 }
+            format.json { status 204 }
+            format.html { redirect(images_url) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/instance_states.rb b/server/lib/deltacloud/collections/instance_states.rb
new file mode 100644
index 0000000..56c1561
--- /dev/null
+++ b/server/lib/deltacloud/collections/instance_states.rb
@@ -0,0 +1,57 @@
+# 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 Deltacloud::Collections
+  class InstanceStates < Base
+
+    collection :instance_states do
+      operation :index do
+        control do
+          @machine = driver.instance_state_machine
+          respond_to do |format|
+            format.xml { haml :'instance_states/show', :layout => false }
+            format.json do
+              out = []
+              @machine.states.each do |state|
+                transitions = state.transitions.collect do |t|
+                  t.automatically? ? {:to => t.destination, :auto => 'true'} : {:to => t.destination, :action => t.action}
+                end
+                out << { :name => state, :transitions => transitions }
+              end
+              out.to_json
+            end
+            format.html { haml :'instance_states/show'}
+            format.gv { erb :"instance_states/show" }
+            format.png do
+              # Trick respond_to into looking up the right template for the
+              # graphviz file
+              gv = erb(:"instance_states/show")
+              png =  ''
+              cmd = 'dot -Kdot -Gpad="0.2,0.2" -Gsize="5.0,8.0" -Gdpi="180" -Tpng'
+              Open3.popen3( cmd ) do |stdin, stdout, stderr|
+                stdin.write( gv )
+                stdin.close()
+                png = stdout.read
+              end
+              content_type 'image/png'
+              png
+            end
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/instances.rb b/server/lib/deltacloud/collections/instances.rb
new file mode 100644
index 0000000..5202149
--- /dev/null
+++ b/server/lib/deltacloud/collections/instances.rb
@@ -0,0 +1,103 @@
+# 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 Deltacloud::Collections
+  class Instances < Base
+
+    include Deltacloud::InstanceFeatures
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    new_route_for(:instances) do
+      @instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
+      @image   = Image.new( :id => params[:image_id] )
+      @hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
+      @realms = [Realm.new(:id => params[:realm_id])] if params[:realm_id]
+      @realms ||= driver.realms(credentials)
+    end
+
+    collection :instances do
+
+      standard_show_operation
+      standard_index_operation
+
+      operation :create, :with_capability => :create_instance do
+        param :image_id,     :string, :required
+        param :realm_id,     :string, :optional
+        param :hwp_id,       :string, :optional
+        control do
+          @instance = driver.create_instance(credentials, params[:image_id], params)
+          if @instance.kind_of? Array
+            @elements = @instance
+            action_handler = "index"
+          else
+            response['Location'] = instance_url(@instance.id)
+            action_handler = "show"
+          end
+          status 201  # Created
+          respond_to do |format|
+            format.xml  { haml :"instances/#{action_handler}" }
+            format.json { xml_to_json("instances/#{action_handler}") }
+            format.html do
+              if @elements
+                haml :"instances/index"
+              elsif @instance and @instance.id
+                response['Location'] = instance_url(@instance.id)
+                haml :"instances/show"
+              else
+                redirect instances_url
+              end
+            end
+          end
+        end
+      end
+
+      action :reboot, :with_capability => :reboot_instance do
+        description "Reboot a running instance."
+        control { instance_action(:reboot) }
+      end
+
+      action :start, :with_capability => :start_instance do
+        description "Start an instance."
+        control { instance_action(:start) }
+      end
+
+      action :stop, :with_capability => :stop_instance do
+        description "Stop a running instance."
+        control { instance_action(:stop) }
+      end
+
+      operation :destroy, :with_capability => :destroy_instance do
+        control { instance_action(:destroy) }
+      end
+
+      action :run, :with_capability => :run_instance do
+        param :id,          :string,  :required
+        param :cmd,         :string,  :required, [], "Shell command to run on instance"
+        param :private_key, :string,  :optional, [], "Private key in PEM format for authentication"
+        param :password,    :string,  :optional, [], "Password used for authentication"
+        control do
+          @output = driver.run_on_instance(credentials, params)
+          respond_to do |format|
+            format.xml { haml :"instances/run" }
+            format.html { haml :"instances/run" }
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/keys.rb b/server/lib/deltacloud/collections/keys.rb
new file mode 100644
index 0000000..55d0fa8
--- /dev/null
+++ b/server/lib/deltacloud/collections/keys.rb
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class Keys < Base
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    get route_for('/keys/new') do
+      respond_to do |format|
+        format.html { haml :"keys/new" }
+      end
+    end
+
+    collection :keys do
+
+      standard_show_operation
+      standard_index_operation
+
+      operation :create, :with_capability => :create_key do
+        param :name,  :string,  :required
+        control do
+          @key = driver.create_key(credentials, { :key_name => params[:name] })
+          status 201
+          response['Location'] = key_url(@key.id)
+          respond_to do |format|
+            format.xml  { haml :"keys/show", :ugly => true }
+            format.html { haml :"keys/show" }
+            format.json { convert_to_json(:key, @key)}
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_key do
+        control do
+          driver.destroy_key(credentials, { :id => params[:id]})
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(keys_url) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/load_balancers.rb b/server/lib/deltacloud/collections/load_balancers.rb
new file mode 100644
index 0000000..d093ead
--- /dev/null
+++ b/server/lib/deltacloud/collections/load_balancers.rb
@@ -0,0 +1,85 @@
+# 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 Deltacloud::Collections
+  class LoadBalancers < Base
+    check_capability :for => lambda { |m| driver.has_capability? m }
+
+    collection :load_balancers do
+      description "Load balancers are used distribute workload across multiple instances"
+
+      standard_index_operation
+      standard_show_operation
+
+      operation :create do
+        param :name,  :string,  :required
+        param :realm_id,  :string,  :required
+        param :listener_protocol,  :string,  :required, ['HTTP', 'TCP']
+        param :listener_balancer_port,  :string,  :required
+        param :listener_instance_port,  :string,  :required
+        control do
+          @load_balancer = driver.create_load_balancer(credentials, params)
+          status 201  # Created
+          response['Location'] = load_balancer_url(@instance.id)
+          respond_to do |format|
+            format.xml  { haml :"load_balancers/show" }
+            format.json { convert_to_json(:load_balancer, @load_balancer) }
+            format.html { haml :"load_balancers/show" }
+          end
+        end
+      end
+
+      action :register do
+        param :instance_id, :string,  :required
+        control do
+          driver.lb_register_instance(credentials, params)
+          @load_balancer = driver.load_balancer(credential, params[:id])
+          respond_to do |format|
+            format.xml { haml :'load_balancers/show' }
+            format.json ( xml_to_json('load_balancers/show'))
+            format.html { haml :'load_balancers/show' }
+          end
+        end
+      end
+
+      action :unregister do
+        param :instance_id, :string,  :required
+        control do
+          driver.lb_unregister_instance(credentials, params)
+          @load_balancer = driver.load_balancer(credential, params[:id])
+          respond_to do |format|
+            format.xml { haml :'load_balancers/show' }
+            format.json ( xml_to_json('load_balancers/show'))
+            format.html { haml :'load_balancers/show' }
+          end
+        end
+      end
+
+      operation :destroy do
+        control do
+          driver.destroy_load_balancer(credentials, params[:id])
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(load_balancers_url) }
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/realms.rb b/server/lib/deltacloud/collections/realms.rb
new file mode 100644
index 0000000..3f21625
--- /dev/null
+++ b/server/lib/deltacloud/collections/realms.rb
@@ -0,0 +1,27 @@
+# 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 Deltacloud::Collections
+  class Realms < Base
+
+    collection :realms do
+      description "Within a cloud provider a realm represents a boundary containing resources"
+
+      standard_index_operation
+      standard_show_operation
+
+    end
+  end
+end
diff --git a/server/lib/deltacloud/collections/storage_snapshots.rb b/server/lib/deltacloud/collections/storage_snapshots.rb
new file mode 100644
index 0000000..b468614
--- /dev/null
+++ b/server/lib/deltacloud/collections/storage_snapshots.rb
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module Deltacloud::Collections
+  class StorageSnapshots < Base
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    new_route_for(:storage_snapshots)
+
+    collection :storage_snapshots do
+      standard_index_operation
+      standard_show_operation
+
+      operation :create, :with_capability => :create_storage_snapshot do
+        param :volume_id, :string,  :required
+        control do
+          @storage_snapshot = driver.create_storage_snapshot(credentials, params)
+          status 201  # Created
+          response['Location'] = storage_snapshot_url(@storage_snapshot.id)
+          show(:storage_snapshot)
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_storage_snapshot do
+        control do
+          driver.destroy_storage_snapshot(credentials, params)
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(storage_snapshots_url) }
+          end
+        end
+      end
+    end
+
+  end
+end
diff --git a/server/lib/deltacloud/collections/storage_volumes.rb b/server/lib/deltacloud/collections/storage_volumes.rb
new file mode 100644
index 0000000..9cdcd66
--- /dev/null
+++ b/server/lib/deltacloud/collections/storage_volumes.rb
@@ -0,0 +1,99 @@
+# 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 Deltacloud::Collections
+  class StorageVolumes < Base
+
+    check_capability :for => lambda { |m| driver.respond_to? m }
+    check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
+
+    new_route_for(:storage_volumes)
+
+    get route_for("/storage_volumes/:id/attach_instance") do
+      @instances = driver.instances(credentials)
+      respond_to do |format|
+        format.html{ haml :"storage_volumes/attach"}
+      end
+    end
+
+    collection :storage_volumes do
+
+      standard_index_operation
+      standard_show_operation
+
+      operation :show, :with_capability => :storage_volume do
+        control { show(:storage_volume) }
+      end
+
+      operation :create do
+        param :snapshot_id, :string,  :optional
+        param :capacity,    :string,  :optional
+        param :realm_id,    :string,  :optional
+        control do
+          @storage_volume = driver.create_storage_volume(credentials, params)
+          status 201
+          response['Location'] = storage_volume_url(@storage_volume.id)
+          respond_to do |format|
+            format.xml  { haml :"storage_volumes/show" }
+            format.html { haml :"storage_volumes/show" }
+            format.json { convert_to_json(:storage_volume, @storage_volume) }
+          end
+        end
+      end
+
+      action :attach, :with_capability => :attach_storage_volume do
+        param :instance_id,:string,  :required
+        param :device,     :string,  :required
+        control do
+          @storage_volume = driver.attach_storage_volume(credentials, params)
+          status 202
+          respond_to do |format|
+            format.html { redirect(storage_volume_url(params[:id]))}
+            format.xml  { haml :"storage_volumes/show" }
+            format.json { convert_to_json(:storage_volume, @storage_volume) }
+          end
+        end
+      end
+
+      action :detach, :with_capability => :detach_storage_volume do
+        control do
+          volume = driver.storage_volume(credentials, :id => params[:id])
+          @storage_volume =  driver.detach_storage_volume(credentials, :id => volume.id, 
+                                                          :instance_id => volume.instance_id,
+                                                          :device => volume.device)
+          status 202
+          respond_to do |format|
+            format.html { redirect(storage_volume_url(params[:id]))}
+            format.xml  { haml :"storage_volumes/show" }
+            format.json { convert_to_json(:storage_volume, @storage_volume) }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_storage_volume do
+        control do
+          driver.destroy_storage_volume(credentials, params)
+          status 204
+          respond_to do |format|
+            format.xml
+            format.json
+            format.html { redirect(storage_volumes_url) }
+          end
+        end
+      end
+
+    end
+  end
+end
-- 
1.7.10