fog--fog/lib/fog/storage/ninefold.rb

127 lines
4.0 KiB
Ruby
Raw Normal View History

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