[ninefold|storage] Framework + request method for Ninefold storage

This commit is contained in:
Lincoln Stoll 2011-06-27 17:55:01 +10:00
parent 91cd448c0f
commit af404bb5ef
5 changed files with 144 additions and 6 deletions

View File

@ -5,6 +5,8 @@ class Ninefold < Fog::Bin
case key
when :compute
Fog::Compute::Ninefold
when :storage
Fog::Storage::Ninefold
else
raise ArgumentError, "Unsupported #{self} service: #{key}"
end
@ -16,6 +18,9 @@ class Ninefold < Fog::Bin
when :compute
Formatador.display_line("[yellow][WARN] Ninefold[:compute] is deprecated, use Compute[:ninefold] instead[/]")
Fog::Compute.new(:provider => 'Ninefold')
when :storage
Formatador.display_line("[yellow][WARN] Ninefold[:storage] is deprecated, use Storage[:ninefold] instead[/]")
Fog::Storage.new(:provider => 'Ninefold')
else
raise ArgumentError, "Unrecognized service: #{service}"
end

View File

@ -6,6 +6,7 @@ module Fog
extend Fog::Provider
service(:compute, 'compute/ninefold')
service(:storage, 'storage/ninefold')
end
end

View File

@ -17,6 +17,9 @@ module Fog
when :local
require 'fog/storage/local'
Fog::Storage::Local.new(attributes)
when :ninefold
require 'fog/storage/ninefold'
Fog::Storage::Ninefold.new(attributes)
when :rackspace
require 'fog/storage/rackspace'
Fog::Storage::Rackspace.new(attributes)
@ -27,7 +30,7 @@ module Fog
def self.directories
directories = []
for provider in [:aws, :google, :local, :rackspace]
for provider in [:aws, :google, :local, :ninefold, :rackspace]
begin
directories.concat(self[provider].directories)
rescue # ignore any missing credentials/etc
@ -50,16 +53,16 @@ module Fog
0
end
end
def self.parse_data(data)
metadata = {
:body => nil,
:headers => {}
}
metadata[:body] = data
metadata[:headers]['Content-Length'] = get_body_size(data)
if data.respond_to?(:path) and !data.path.nil?
filename = ::File.basename(data.path)
unless (mime_types = MIME::Types.of(filename)).empty?
@ -69,6 +72,6 @@ module Fog
# metadata[:headers]['Content-MD5'] = Base64.encode64(Digest::MD5.digest(metadata[:body])).strip
metadata
end
end
end

126
lib/fog/storage/ninefold.rb Normal file
View File

@ -0,0 +1,126 @@
require 'base64'
require 'hmac-sha1'
module Fog
module Storage
class Ninefold < Fog::Service
STORAGE_HOST = "onlinestorage.ninefold.com" #"api.ninefold.com"
STORAGE_PATH = "" #"/storage/v1.0"
STORAGE_PORT = "80" # "443"
STORAGE_SCHEME = "http" # "https"
requires :ninefold_storage_token, :ninefold_storage_secret
model_path 'fog/storage/models/ninefold'
# model :directory
# collection :directories
# model :file
# collection :files
request_path 'fog/storage/requests/ninefold'
# request :delete_container
module Utils
end
class Mock
include Utils
def initialize(options={})
require 'mime/types'
@ninefold_storage_token = options[:ninefold_storage_token]
@ninefold_storage_secret = options[:ninefold_storage_secret]
end
def request(options)
raise "Ninefold Storage mocks not implemented"
end
end
class Real
include Utils
def initialize(options={})
require 'mime/types'
@ninefold_storage_token = options[:ninefold_storage_token]
@ninefold_storage_secret = options[:ninefold_storage_secret]
@ninefold_storage_secret_decoded = Base64.decode64( @ninefold_storage_secret )
Excon.ssl_verify_peer = false if options[:rackspace_servicenet] == true
@connection = Fog::Connection.new("#{Fog::Storage::Ninefold::STORAGE_SCHEME}://#{Fog::Storage::Ninefold::STORAGE_HOST}:#{Fog::Storage::Ninefold::STORAGE_PORT}", true) # persistent
end
def reload
@connection.reset
end
def request(params, &block)
req_path = params[:path]
# Force set host and port
params.merge!({
:host => Fog::Storage::Ninefold::STORAGE_HOST,
:path => "#{Fog::Storage::Ninefold::STORAGE_PATH}/rest/#{params[:path]}",
})
# Set default method and headers
params = {:method => 'GET', :headers => {}}.merge params
params[:headers]["Content-Type"] ||= "application/octet-stream"
# Add request date
params[:headers]["date"] = Time.now().httpdate()
params[:headers]["x-emc-uid"] = @ninefold_storage_token
# Build signature string
signstring = ""
signstring += params[:method]
signstring += "\n"
signstring += params[:headers]["Content-Type"]
signstring += "\n"
if( params[:headers]["range"] )
signstring += params[:headers]["range"]
end
signstring += "\n"
signstring += params[:headers]["date"]
signstring += "\n"
signstring += "/rest/" + URI.unescape( req_path ).downcase
signstring += params[:query] if params[:query]
signstring += "\n"
customheaders = {}
params[:headers].each { |key,value|
if key == "x-emc-date"
#skip
elsif key =~ /^x-emc-/
customheaders[ key.downcase ] = value
end
}
header_arr = customheaders.sort()
first = true
header_arr.each { |key,value|
# Values are lowercase and whitespace-normalized
signstring += key + ":" + value.strip.chomp.squeeze( " " ) + "\n"
}
digest = ::HMAC::SHA1.digest( @ninefold_storage_secret_decoded, signstring.chomp() )
signature = Base64.encode64( digest ).chomp()
params[:headers]["x-emc-signature"] = signature
begin
response = @connection.request(params, &block)
rescue Excon::Errors::HTTPStatusError => error
raise case error
when Excon::Errors::NotFound
Fog::Storage::Ninefold::NotFound.slurp(error)
else
error
end
end
response
end
end
end
end
end

View File

@ -9,8 +9,11 @@ def storage_providers
:local => {
:mocked => false
},
:ninefold => {
:mocked => false
},
:rackspace => {
:mocked => false
}
}
end
end