Class: SwiftStorage::Service

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
SwiftStorage, Utils
Defined in:
lib/swift_storage/service.rb

Constant Summary

Constants included from SwiftStorage

VERSION

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SwiftStorage

configure

Methods included from Utils

#hmac, #sig_to_hex, #struct

Constructor Details

#initialize(tenant: configuration.tenant, username: configuration.username, password: configuration.password, endpoint: configuration.endpoint, ssl_verify: configuration.ssl_verify, temp_url_key: configuration.temp_url_key, retries: configuration.retries) ⇒ Service

Returns a new instance of Service.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/swift_storage/service.rb', line 27

def initialize(tenant: configuration.tenant,
               username: configuration.username,
               password: configuration.password,
               endpoint: configuration.endpoint,
               ssl_verify: configuration.ssl_verify,
               temp_url_key: configuration.temp_url_key,
               retries: configuration.retries)
  @ssl_verify = ssl_verify
  @temp_url_key = temp_url_key
  @retries = retries

  %w(tenant username password endpoint).each do |n|
    eval("#{n} or raise ArgumentError, '#{n} is required'")
    eval("@#{n} = #{n}")
  end

  setup_auth
  @sessions = {}
end

Instance Attribute Details

#auth_atObject (readonly)

Returns the value of attribute auth_at.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def auth_at
  @auth_at
end

#auth_tokenObject (readonly)

Returns the value of attribute auth_token.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def auth_token
  @auth_token
end

#endpointObject (readonly)

Returns the value of attribute endpoint.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def endpoint
  @endpoint
end

#expiresObject (readonly)

Returns the value of attribute expires.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def expires
  @expires
end

#retriesObject (readonly)

Returns the value of attribute retries.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def retries
  @retries
end

#ssl_verifyObject (readonly)

Returns the value of attribute ssl_verify.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def ssl_verify
  @ssl_verify
end

#storage_hostObject (readonly)

Returns the value of attribute storage_host.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def storage_host
  @storage_host
end

#storage_pathObject (readonly)

Returns the value of attribute storage_path.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def storage_path
  @storage_path
end

#storage_portObject (readonly)

Returns the value of attribute storage_port.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def storage_port
  @storage_port
end

#storage_schemeObject (readonly)

Returns the value of attribute storage_scheme.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def storage_scheme
  @storage_scheme
end

#storage_tokenObject (readonly)

Returns the value of attribute storage_token.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def storage_token
  @storage_token
end

#storage_urlObject

Returns the value of attribute storage_url.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def storage_url
  @storage_url
end

#temp_url_keyObject (readonly)

Returns the value of attribute temp_url_key.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def temp_url_key
  @temp_url_key
end

#tenantObject (readonly)

Returns the value of attribute tenant.



12
13
14
# File 'lib/swift_storage/service.rb', line 12

def tenant
  @tenant
end

Class Method Details

.escape(str, extra_exclude_chars = '') ⇒ Object

CGI.escape, but without special treatment on spaces



108
109
110
111
112
# File 'lib/swift_storage/service.rb', line 108

def self.escape(str, extra_exclude_chars = '')
  str.gsub(/([^a-zA-Z0-9_.-#{extra_exclude_chars}]+)/) do
    '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
  end
end

Instance Method Details

#accountObject



62
63
64
# File 'lib/swift_storage/service.rb', line 62

def 
  @account ||= SwiftStorage::Account.new(self, tenant)
end

#containersObject



58
59
60
# File 'lib/swift_storage/service.rb', line 58

def containers
  @container_collection ||= SwiftStorage::ContainerCollection.new(self)
end

#create_temp_url(container, object, expires, method, ssl = true, params = {}) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/swift_storage/service.rb', line 75

def create_temp_url(container, object, expires, method, ssl = true, params = {})
  scheme = ssl ? 'https' : 'http'

  method = method.to_s.upcase
  # Limit methods
  %w{GET POST PUT HEAD}.include?(method) or raise ArgumentError, 'Only GET, POST, PUT, HEAD supported'

  expires = expires.to_i
  object_path_escaped = File.join(storage_path, escape(container), escape(object, '/'))
  object_path_unescaped = File.join(storage_path, escape(container), object)

  string_to_sign = "#{method}\n#{expires}\n#{object_path_unescaped}"

  sig = sig_to_hex(hmac('sha1', temp_url_key, string_to_sign))

  klass = (scheme == 'http') ? URI::HTTP : URI::HTTPS

  temp_url_options = {
    scheme: scheme,
    host: storage_host,
    port: storage_port,
    path: object_path_escaped,
    query: URI.encode_www_form(
      params.merge(
        temp_url_sig: sig,
        temp_url_expires: expires)
    )
  }
  klass.build(temp_url_options).to_s
end

#escape(*args) ⇒ Object



114
115
116
# File 'lib/swift_storage/service.rb', line 114

def escape(*args)
  self.class.escape(*args)
end

#request(path_or_url, method: :get, headers: nil, params: nil, json_data: nil, input_stream: nil, output_stream: nil) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/swift_storage/service.rb', line 118

def request(path_or_url,
            method: :get,
            headers: nil,
            params: nil,
            json_data: nil,
            input_stream: nil,
            output_stream: nil)

  tries = retries

  headers ||= {}
  headers.merge!(Headers::AUTH_TOKEN => auth_token) if authenticated?
  headers.merge!(Headers::CONTENT_TYPE => 'application/json') if json_data
  headers.merge!(Headers::CONNECTION => 'keep-alive', Headers::PROXY_CONNECTION => 'keep-alive')

  if !(path_or_url =~ /^http/)
    path_or_url = File.join(storage_url, path_or_url)
  end

  # Cache HTTP session as url with no path (scheme, host, port)
  uri = URI.parse(URI.escape path_or_url)
  path = uri.query ? uri.path + '?' + uri.query : uri.path
  uri.path = ''
  uri.query = nil

  case method
  when :get
    if params.respond_to?(:to_hash)
      params.reject!{|k,v| v.nil?}
      path << '?'
      path << URI.encode_www_form(params)
    end
    req = Net::HTTP::Get.new(path, headers)
  when :delete
    req = Net::HTTP::Delete.new(path, headers)
  when :head
    req = Net::HTTP::Head.new(path, headers)
  when :post
    req = Net::HTTP::Post.new(path, headers)
  when :put
    req = Net::HTTP::Put.new(path, headers)
  when :copy
    req = Net::HTTP::Copy.new(path, headers)
  else
    raise ArgumentError, "Method #{method} not supported"
  end

  if json_data
    req.body = JSON.generate(json_data)
  end

  if input_stream
    if String === input_stream
      input_stream = StringIO.new(input_stream)
    end
    req.body_stream = input_stream
    req.content_length = input_stream.size
  end

  if output_stream
    output_proc = proc do |response|
      response.read_body do |chunk|
        output_stream.write(chunk)
      end
    end
  end

  response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless ssl_verify
    http.request(req, &output_proc)
  end

  case response
  when Net::HTTPSuccess, Net::HTTPRedirection
    return response
  else
    raise_error!(response)
  end
rescue AuthError => e
  # If token is at least 60 second old, we try to get a new one
  raise e unless @auth_at && (Time.now - @auth_at).to_i > 60
  authenticate!
  retry
rescue Errno::EPIPE, Timeout::Error, Errno::EINVAL, EOFError
  # Server closed the connection, retry
  sleep 5
  retry unless (tries -= 1) <= 0
  raise SwiftStorage::Errors::ServerError, "Unable to connect to OpenStack::Swift after #{retries} retries"
end

#setup_authObject



47
48
49
50
51
52
53
54
55
56
# File 'lib/swift_storage/service.rb', line 47

def setup_auth
  case configuration.auth_version
  when '1.0'
    extend SwiftStorage::Auth::V1_0
  when '2.0'
    extend SwiftStorage::Auth::V2_0
  else
    fail "Unsupported auth version #{configuration.auth_version}"
  end
end