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 2012/11/19 15:54:04 UTC
Initial StorageVolume support for the Openstack driver
Hi, these patches (2 and 3) add storage volumes support for the
Openstack driver. This relies on getting the latest version of
the Openstack rubygem - 1.0.7 which is currently available.
More info/write-up about how/why when adding this functionality
in both the gem and deltacloud is at
http://mariosandreou.com/deltacloud/cloud_API/2012/11/19/deltacloud-openstack-driver-volumes.html
marios
[PATCH 1/3] Fix bug in images show.xml ... hwp.name vs hwp.id
Posted by ma...@redhat.com.
From: marios <ma...@redhat.com>
Signed-off-by: marios <ma...@redhat.com>
---
server/views/images/show.xml.haml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/views/images/show.xml.haml b/server/views/images/show.xml.haml
index 66b4f9a..6350706 100644
--- a/server/views/images/show.xml.haml
+++ b/server/views/images/show.xml.haml
@@ -12,7 +12,7 @@
- if @image.hardware_profiles
%hardware_profiles
- @image.hardware_profiles.each do |profile|
- %hardware_profile{ :href => hardware_profile_url(profile.name), :id => profile.name, :rel => :hardware_profile }
+ %hardware_profile{ :href => hardware_profile_url(profile.id), :id => profile.id, :rel => :hardware_profile }
%actions
%link{ :rel => 'create_instance', :method => :post, :href => "#{instances_url};image_id=#{@image.id}"}
%link{ :rel => 'destroy_image', :method => :delete, :href => "#{destroy_image_url(@image.id)}" }
--
1.7.11.7
[PATCH 2/3] Add features and attributes for Openstack block storage volumes
Posted by ma...@redhat.com.
From: marios <ma...@redhat.com>
Signed-off-by: marios <ma...@redhat.com>
---
server/lib/deltacloud/collections/storage_volumes.rb | 4 ++++
server/lib/deltacloud/drivers/features.rb | 19 +++++++++++++++++++
server/lib/deltacloud/models/storage_volume.rb | 1 +
3 files changed, 24 insertions(+)
diff --git a/server/lib/deltacloud/collections/storage_volumes.rb b/server/lib/deltacloud/collections/storage_volumes.rb
index 0b52045..bc505cb 100644
--- a/server/lib/deltacloud/collections/storage_volumes.rb
+++ b/server/lib/deltacloud/collections/storage_volumes.rb
@@ -16,6 +16,8 @@
module Deltacloud::Collections
class StorageVolumes < Base
+ include Deltacloud::Features
+
set :capability, lambda { |m| driver.respond_to? m }
check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
@@ -37,6 +39,8 @@ module Deltacloud::Collections
param :snapshot_id, :string, :optional
param :capacity, :string, :optional
param :realm_id, :string, :optional
+ param :name, :string, :optional
+ param :description, :string, :optional
control do
@storage_volume = driver.create_storage_volume(credentials, params)
status 201
diff --git a/server/lib/deltacloud/drivers/features.rb b/server/lib/deltacloud/drivers/features.rb
index 3e1b704..ca4e19a 100644
--- a/server/lib/deltacloud/drivers/features.rb
+++ b/server/lib/deltacloud/drivers/features.rb
@@ -163,6 +163,25 @@ module Deltacloud
end
end
+ feature :volume_name, :for => :storage_volumes do
+ description "Specify name when creating storage_volume"
+ operation :create do
+ param :name, :string, :optional
+ end
+ end
+
+ feature :volume_description, :for => :storage_volumes do
+ description "Specify description when creating storage_volume"
+ operation :create do
+ param :description, :string, :optional
+ end
+ end
+
+
+
+
+
+
end
end
diff --git a/server/lib/deltacloud/models/storage_volume.rb b/server/lib/deltacloud/models/storage_volume.rb
index 0722395..7aa00a9 100644
--- a/server/lib/deltacloud/models/storage_volume.rb
+++ b/server/lib/deltacloud/models/storage_volume.rb
@@ -26,5 +26,6 @@ class StorageVolume < BaseModel
attr_accessor :actions
attr_accessor :name
attr_accessor :kind
+ attr_accessor :description # openstack volumes have a display_description attr
end
--
1.7.11.7
[PATCH 3/3] Adds storage volume support for deltacloud driver
Posted by ma...@redhat.com.
From: marios <ma...@redhat.com>
needs openstack gem 1.0.7
Signed-off-by: marios <ma...@redhat.com>
---
server/deltacloud-core.gemspec | 2 +-
.../drivers/openstack/openstack_driver.rb | 153 +++++++++++++++++----
2 files changed, 125 insertions(+), 30 deletions(-)
diff --git a/server/deltacloud-core.gemspec b/server/deltacloud-core.gemspec
index cb9a8c8..3117a0e 100644
--- a/server/deltacloud-core.gemspec
+++ b/server/deltacloud-core.gemspec
@@ -104,7 +104,7 @@ Gem::Specification.new do |s|
s.add_dependency('uuidtools', '>= 2.1.1')
# Openstack Compute and Object-Storage
- s.add_dependency('openstack', '>= 1.0.6')
+ s.add_dependency('openstack', '>= 1.0.7')
# Aruba Cloud
s.add_dependency('savon', '>= 1.0.0')
diff --git a/server/lib/deltacloud/drivers/openstack/openstack_driver.rb b/server/lib/deltacloud/drivers/openstack/openstack_driver.rb
index 6425d1b..2bf45ab 100644
--- a/server/lib/deltacloud/drivers/openstack/openstack_driver.rb
+++ b/server/lib/deltacloud/drivers/openstack/openstack_driver.rb
@@ -30,6 +30,8 @@ module Deltacloud
feature :instances, :user_data
feature :images, :user_name
feature :keys, :import_key
+ feature :storage_volumes, :volume_name
+ feature :storage_volumes, :volume_description
define_instance_states do
start.to( :pending ) .on( :create )
@@ -46,9 +48,14 @@ module Deltacloud
#get the collections as defined by 'capability' and 'respond_to?' blocks
super_collections = super
begin
- new_client(credentials, :buckets)
+ new_client(credentials, "object-store")
rescue Deltacloud::Exceptions::NotImplemented #OpenStack::Exception::NotImplemented...
- return super_collections - [Sinatra::Rabbit::BucketsCollection]
+ super_collections = super_collections - [Sinatra::Rabbit::BucketsCollection]
+ end
+ begin
+ new_client(credentials, "volume")
+ rescue Deltacloud::Exceptions::NotImplemented
+ super_collections = super_collections - [Sinatra::Rabbit::StorageVolumesCollection]
end
super_collections
end
@@ -138,19 +145,19 @@ module Deltacloud
def instances(credentials, opts={})
os = new_client(credentials)
- insts = []
+ insts = attachments = []
safely do
if opts[:id]
begin
server = os.get_server(opts[:id])
- insts << convert_from_server(server, os.connection.authuser)
+ insts << convert_from_server(server, os.connection.authuser, get_attachments(opts[:id], os))
rescue => e
raise e unless e.message =~ /The resource could not be found/
insts = []
end
else
insts = os.list_servers_detail.collect do |s|
- convert_from_server(s, os.connection.authuser)
+ convert_from_server(s, os.connection.authuser,get_attachments(s[:id], os))
end
end
end
@@ -179,7 +186,7 @@ module Deltacloud
end
safely do
server = os.create_server(params)
- result = convert_from_server(server, os.connection.authuser)
+ result = convert_from_server(server, os.connection.authuser, get_attachments(server.id, os))
end
result
end
@@ -189,7 +196,7 @@ module Deltacloud
safely do
server = os.get_server(instance_id)
server.reboot! # sends a hard reboot (power cycle) - could instead server.reboot("SOFT")
- convert_from_server(server, os.connection.authuser)
+ convert_from_server(server, os.connection.authuser, get_attachments(instance_id, os))
end
end
@@ -222,7 +229,7 @@ module Deltacloud
end
def buckets(credentials, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
buckets = []
safely do
if opts[:id]
@@ -235,7 +242,7 @@ module Deltacloud
end
def create_bucket(credentials, name, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
bucket = nil
safely do
bucket = os.create_container(name)
@@ -244,14 +251,14 @@ module Deltacloud
end
def delete_bucket(credentials, name, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
safely do
os.delete_container(name)
end
end
def blobs(credentials, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
blobs = []
safely do
bucket = os.container(opts['bucket'])
@@ -265,7 +272,7 @@ module Deltacloud
end
def blob_data(credentials, bucket, blob, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
safely do
os.container(bucket).object(blob).data_stream do |chunk|
yield chunk
@@ -274,7 +281,7 @@ module Deltacloud
end
def create_blob(credentials, bucket, blob, data, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
safely do
BlobHelper.rename_metadata_headers(opts, "X-Object-Meta-")
os_blob = os.container(bucket).create_object(blob, {:content_type=> data[:type], :metadata=>opts}, data[:tempfile])
@@ -283,21 +290,21 @@ module Deltacloud
end
def delete_blob(credentials, bucket, blob, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
safely do
os.container(bucket).delete_object(blob)
end
end
def blob_metadata(credentials, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
safely do
os.container(opts['bucket']).object(opts[:id]).metadata
end
end
def update_blob_metadata(credentials, opts={})
- os = new_client(credentials, :buckets)
+ os = new_client(credentials, "object-store")
safely do
BlobHelper.rename_metadata_headers(opts["meta_hash"], "")
blob = os.container(opts['bucket']).object(opts[:id])
@@ -352,10 +359,82 @@ module Deltacloud
end
end
+ def storage_volumes(credentials, opts={})
+ vs = new_client(credentials, "volume")
+ volumes = []
+ safely do
+ if opts[:id]
+ volumes << convert_volume(vs.get_volume(opts[:id]))
+ else
+ vs.volumes.each do |vol|
+ volumes << convert_volume(vol)
+ end
+ end
+ end
+ volumes
+ end
+
+ def create_storage_volume(credentials, opts=nil)
+ vs = new_client(credentials, "volume")
+ params = {}
+ safely do
+ params[:size] = opts.delete("capacity") || 1
+ params[:display_name] = opts.delete("name") || "Volume#{Time.now}"
+ params[:display_description] = opts.delete("description") || params[:display_name]
+ params[:availability_zone] = opts.delete("realm_id") unless (opts["realm_id"].nil? || opts["realm_id"].empty?)
+ opts.delete("commit")
+ opts.delete("snapshot_id") #FIXME AFTER ADDING SNAPSHOTS TO OPENSTACK GEM
+ volume = convert_volume(vs.create_volume(opts.merge(params)))
+ end
+ end
+
+ def destroy_storage_volume(credentials, opts={})
+ vs = new_client(credentials, "volume")
+ safely do
+ vs.delete_volume(opts[:id])
+ end
+ end
+
+ def attach_storage_volume(credentials, opts={})
+ vs = new_client(credentials, "volume")
+ cs = new_client(credentials, "compute")
+ safely do
+ cs.attach_volume(opts[:instance_id], opts[:id], opts[:device])
+ volume = convert_volume(vs.get_volume(opts[:id]))
+ end
+ end
+
+ def detach_storage_volume(credentials, opts={})
+ vs = new_client(credentials, "volume")
+ cs = new_client(credentials, "compute")
+ safely do
+ cs.detach_volume(opts[:instance_id], opts[:id])
+ volume = convert_volume(vs.get_volume(opts[:id]))
+ end
+ end
+
+ def storage_snapshots(credentials, opts={})
+ vs = new_client(credentials, "volume")
+ safely do
+ end
+ end
+
+ def create_storage_snapshot(credentials, opts={})
+ vs = new_client(credentials, "volume")
+ safely do
+ end
+ end
+
+ def destroy_storage_snapshot(credentials, opts={})
+ vs = new_client(credentials, "volume")
+ safely do
+ end
+ end
+
private
#for v2 authentication credentials.name == "username+tenant_name"
- def new_client(credentials, type = :compute)
+ def new_client(credentials, type = "compute")
tokens = credentials.user.split("+")
if credentials.user.empty?
raise AuthenticationFailure.new(Exception.new("Error: you must supply the username"))
@@ -366,16 +445,10 @@ private
user_name, tenant_name = tokens.first, tokens.last
end
safely do
- case type
- when :compute
- OpenStack::Connection.create(:username => user_name, :api_key => credentials.password, :authtenant => tenant_name, :auth_url => api_provider)
- when :buckets
- OpenStack::Connection.create(:username => user_name, :api_key => credentials.password, :authtenant => tenant_name, :auth_url => api_provider, :service_type => "object-store")
- else
- raise ValidationFailure.new(Exception.new("Error: tried to initialise Openstack connection using" +
- " an unknown service_type: #{type}"))
- end
- end
+ raise ValidationFailure.new(Exception.new("Error: tried to initialise Openstack connection using" +
+ " an unknown service_type: #{type}")) unless ["volume", "compute", "object-store"].include? type
+ OpenStack::Connection.create(:username => user_name, :api_key => credentials.password, :authtenant => tenant_name, :auth_url => api_provider, :service_type => type)
+ end
end
#NOTE: for the convert_from_foo methods below... openstack-compute
@@ -407,7 +480,7 @@ private
})
end
- def convert_from_server(server, owner)
+ def convert_from_server(server, owner, attachments=[])
op = (server.class == Hash)? :fetch : :send
image = server.send(op, :image)
flavor = server.send(op, :flavor)
@@ -430,7 +503,8 @@ private
:private_addresses => convert_server_addresses(server, :private),
:username => 'root',
:password => password,
- :keyname => server.send(op, :key_name)
+ :keyname => server.send(op, :key_name),
+ :storage_volumes => attachments.inject([]){|res, cur| res << {cur[:volumeId] => cur[:device]} ;res}
)
inst.actions = instance_actions_for(inst.state)
inst.create_image = 'RUNNING'.eql?(inst.state)
@@ -489,6 +563,27 @@ private
)
end
+ def get_attachments(server_id, client)
+ if client.api_extensions[:"os-volumes"]
+ attachments = client.list_attachments(server_id)
+ attachments[:volumeAttachments] || []
+ else
+ []
+ end
+ end
+
+ def convert_volume(vol)
+ StorageVolume.new({ :id => vol.id,
+ :name => vol.display_name,
+ :created => vol.created_at,
+ :state => (vol.attachments.inject([]){|res, cur| res << cur if cur.size > 0 ; res}.empty?) ? "AVAILABLE" : "IN-USE",
+ :capacity => vol.size,
+ :instance_id => vol.attachments.first["serverId"],
+ :device =>vol.attachments.first["device"],
+ :realm_id => vol.availability_zone,
+ :description => vol.display_description # openstack volumes have a display_description attr
+ })
+ end
#IN: path1='server_path1'. content1='contents1', path2='server_path2', content2='contents2' etc
#OUT:{local_path=>server_path, local_path1=>server_path2 etc}
--
1.7.11.7