You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by ma...@redhat.com on 2010/08/18 12:12:24 UTC
Blobstore functions - PUT and DELETE /api/containers
This patch implements the PUT /api/containers and DELETE /api/containers operations (create and delete an empty container) for S3 and Cloudfiles. There is a feature/bug which has been causing me problems: after the DELETE operation, for some reason Sinatra then tries to do a GET on the deleted resource... not sure what I'm doing wrong so Michal/David anyone else have you come across this before?
I have added a feature for the Amazon EC2/S3 driver so when you create a container you can optionally specify its location. Valid values are: 'EU'|'us-west1'|'ap-southeast-1E' (europe, US west coast, asia-pacific respectively). If you do not specify a location then the default is used which is 'us-east' (though weirldy if you specify 'us-east' as a location things blow up @ Amazon's end).
I will keep adding new blobstore functions and sending them out incrementally for comments. Once everything is done I will send out one big patch with everything included.
marios
Re: Blobstore functions - PUT and DELETE /api/containers
Posted by Michal Fojtik <mf...@redhat.com>.
Hi Marios,
On 18/08/10 11:12 +0100, mandreou@redhat.com wrote:
>
>This patch implements the PUT /api/containers and DELETE /api/containers operations (create and delete an empty container) for S3 and Cloudfiles. There is a feature/bug which has been causing me problems: after the DELETE operation, for some reason Sinatra then tries to do a GET on the deleted resource... not sure what I'm doing wrong so Michal/David anyone else have you come across this before?
I tried your patch and it's working perfectly. After I delete container it
redirects me to a list of containers, which as I suppose is the correct way
how to do it.
Anyway I found a few issues:
1. When you want to create a container, with some common name (like 'Test')
it throws 'Internal Server Error'. Please catch these exceptions using
safely..end block.
I know that I'm sharing my bucket names with other users, but we need to
throw something 'useful' for a client.
Also please consider using this block for all 'backend-specific' operations.
For this case returning '409 - Conflict' should be fine. Something like:
safely do
begin
if container_location
container = RightAws::S3::Bucket.create(s3_client, name, true, nil, :location => container_location)
else
container = RightAws::S3::Bucket.create(s3_client, name, true)
end
rescue RightAws::AwsError => e
raise e unless e.message =~ /BucketAlreadyExists/
raise Deltacloud::BackendError.new(409, e.class.to_s, e.message, e.backtrace)
end
end
2. When I tried your patch for the first time I got 'no-method-error' when
I accessed some blob item inside container. This error was caused by
missing 'content_type' method in RightAws::S3::Key class.
Workaround is to add 'require "mime/types"' on top of EC2 driver and then
instead of using:
481: :content_type => s3_object.content_type,
use:
481: :content_type => "#{MIME::Types.type_for(s3_object.name)}",
3. Create operation is always POST and not PUT. Should be great if we could
use 'PUT' method for 'putting' new blobs inside container (but I'm not
sure if this HTTP method like uploading ;)
>I have added a feature for the Amazon EC2/S3 driver so when you create a container you can optionally specify its location. Valid values are: 'EU'|'us-west1'|'ap-southeast-1E' (europe, US west coast, asia-pacific respectively). If you do not specify a location then the default is used which is 'us-east' (though weirldy if you specify 'us-east' as a location things blow up @ Amazon's end).
Nice! I tried it and it works as expected.
-- Michal
--
--------------------------------------------------------
Michal Fojtik, mfojtik@redhat.com, +420 532 294 4307
Ruby / Ruby On Rails Developer
Deltacloud API: http://deltacloud.org
--------------------------------------------------------
['PATCH'] New blobstore functions: PUT /api/containers and DELETE /api/containers/:id.
Posted by ma...@redhat.com.
From: marios <ma...@redhat.com>
---
server/lib/deltacloud/base_driver/base_driver.rb | 6 +++
server/lib/deltacloud/base_driver/features.rb | 8 ++++
server/lib/deltacloud/drivers/ec2/ec2_driver.rb | 26 +++++++++++++
.../drivers/rackspace/rackspace_driver.rb | 13 +++++++
.../lib/deltacloud/helpers/application_helper.rb | 7 ++++
server/server.rb | 38 +++++++++++++++++++-
server/views/containers/index.html.haml | 12 +++++-
server/views/containers/new.html.haml | 13 +++++++
8 files changed, 120 insertions(+), 3 deletions(-)
create mode 100644 server/views/containers/new.html.haml
diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
index c21ccfa..a2d1ee3 100644
--- a/server/lib/deltacloud/base_driver/base_driver.rb
+++ b/server/lib/deltacloud/base_driver/base_driver.rb
@@ -197,6 +197,12 @@ module Deltacloud
nil
end
+ def create_container(credentials, name, opts=nil)
+ end
+
+ def delete_container(credentials, name, opts=nil)
+ end
+
def blobs(credentials, opts = nil)
[]
end
diff --git a/server/lib/deltacloud/base_driver/features.rb b/server/lib/deltacloud/base_driver/features.rb
index 3ed4085..af3975e 100644
--- a/server/lib/deltacloud/base_driver/features.rb
+++ b/server/lib/deltacloud/base_driver/features.rb
@@ -162,5 +162,13 @@ module Deltacloud
description "Size instances according to changes to a hardware profile"
# The parameters are filled in from the hardware profiles
end
+
+ declare_feature :containers, :container_location do
+ description "Take extra location parameter for Container creation (e.g. S3, 'eu' or 'us-west-1')"
+ operation :create do
+ param :location, :string, :optional
+ end
+ end
+
end
end
diff --git a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
index 313872c..a47e6d8 100644
--- a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
+++ b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
@@ -43,6 +43,7 @@ class EC2Driver < Deltacloud::BaseDriver
feature :instances, :user_data
feature :instances, :authentication_key
feature :images, :owner_id
+ feature :containers, :container_location
define_hardware_profile('m1.small') do
cpu 1
@@ -292,6 +293,31 @@ class EC2Driver < Deltacloud::BaseDriver
container_list
end
+
+#
+#
+#valid values for bucket location: 'EU'|'us-west1'|'ap-southeast-1' - if you
+#don't specify a location then by default buckets are created in 'us-east'
+#[if you specify 'us-east' things blow up]
+ def create_container(credentials, name, opts={})
+ container = nil
+ s3_client = s3_client(credentials)
+ container_location = opts['location']
+ if container_location
+ container = RightAws::S3::Bucket.create(s3_client, name, true, nil, :location => container_location)
+ else
+ container = RightAws::S3::Bucket.create(s3_client, name, true)
+ end
+ convert_storage_container(container)
+ end
+
+#--
+#delete_container
+#--
+ def delete_container(credentials, name, opts={})
+ s3_client = s3_client(credentials)
+ s3_client.interface.delete_bucket(name)
+ end
#--
# BLOBS get a list of blobs for a given bucket
#--
diff --git a/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb b/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb
index e6fbf97..d15ec68 100644
--- a/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb
+++ b/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb
@@ -168,6 +168,19 @@ class RackspaceDriver < Deltacloud::BaseDriver
container_list
end
+ def create_container(credentials, name, opts)
+ container = nil
+ cf = cloudfiles_client(credentials)
+ new_container = cf.create_container(name)
+ container = convert_container(new_container)
+ container
+ end
+
+ def delete_container(credentials, name, opts)
+ cf = cloudfiles_client(credentials)
+ cf.delete_container(name)
+ end
+
def blobs(credentials, opts)
unless opts['container'] then
raise Deltacloud::Validation::Failure.new(Deltacloud::Validation::Param.new(["container"]), "Error - need container name to retrieve the blob list. You said bucket->#{opts['container']}.")
diff --git a/server/lib/deltacloud/helpers/application_helper.rb b/server/lib/deltacloud/helpers/application_helper.rb
index 9a9dfdc..348e5d6 100644
--- a/server/lib/deltacloud/helpers/application_helper.rb
+++ b/server/lib/deltacloud/helpers/application_helper.rb
@@ -54,6 +54,13 @@ module ApplicationHelper
return 'password' if driver_has_feature?(:authentication_password)
end
+ def driver_has_container_location_feature?
+ driver.features(:containers).each do |feat|
+ return true if feat.name == :container_location
+ end
+ false
+ end
+
def filter_all(model)
filter = {}
filter.merge!(:id => params[:id]) if params[:id]
diff --git a/server/server.rb b/server/server.rb
index e0a61c1..75e63b4 100644
--- a/server/server.rb
+++ b/server/server.rb
@@ -374,6 +374,13 @@ get '/api/containers/:container/:blob' do
end
end
+get '/api/containers/new' do
+ respond_to do |format|
+ format.html { haml :"containers/new" }
+ end
+end
+
+
collection :containers do
description "Cloud Storage Containers - aka buckets|directories|folders"
@@ -390,4 +397,33 @@ collection :containers do
param :id, :string
control { show(:container) }
end
-end
\ No newline at end of file
+
+ operation :create do
+ description "Create a new container (PUT /api/containers)"
+ param :name, :string, :required
+ control do
+ @container = driver.create_container(credentials, params[:name], params)
+ respond_to do |format|
+ format.xml do
+ response.status = 201 # Created
+ response['Location'] = container_url(@container.id)
+ haml :"containers/show"
+ end
+ format.html do
+ redirect container_url(@container.id) if @container and @container.id
+ redirect containers_url
+ end
+ end
+ end
+ end
+
+ operation :destroy do
+ description "Delete a container by name - container must be empty"
+ param :id, :string, :required
+ control do
+ driver.delete_container(credentials, params[:id], params)
+ redirect(containers_url)
+ end
+ end
+
+end
diff --git a/server/views/containers/index.html.haml b/server/views/containers/index.html.haml
index a199ace..9c2c31a 100644
--- a/server/views/containers/index.html.haml
+++ b/server/views/containers/index.html.haml
@@ -1,5 +1,8 @@
%h1
Containers
+%br
+%p
+ =link_to 'Create new container', "/api/containers/new"
%table.display
%thead
@@ -12,7 +15,8 @@
Size
%th
Blob List
-
+ %th
+
%tbody
- @containers.each do |container|
%tr
@@ -24,4 +28,8 @@
= container.size
%td
-container.blob_list.each do |blob|
- = blob
\ No newline at end of file
+ = blob
+ %td
+ =link_to 'Delete', destroy_container_url(container.name), :class => 'delete'
+
+
diff --git a/server/views/containers/new.html.haml b/server/views/containers/new.html.haml
new file mode 100644
index 0000000..4c92e00
--- /dev/null
+++ b/server/views/containers/new.html.haml
@@ -0,0 +1,13 @@
+%h1 New Container
+
+%form{ :action => containers_url, :method => :post }
+ %label
+ Container Name:
+ %input{ :name => 'name', :size => 250}/
+ %br
+ -if driver_has_container_location_feature?
+ %p
+ %label
+ Location: (optional)
+ %input{ :name => 'location', :size => 20 }/
+ %input{ :type => :submit, :name => "commit", :value => "create"}/
\ No newline at end of file
--
1.7.2.1