Class: CloudFiles::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/cloudfiles/connection.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(authuser, authkey, retry_auth = true) ⇒ Connection

Creates a new CloudFiles::Connection object. Uses CloudFiles::Authentication to perform the login for the connection. The authuser is the Rackspace Cloud username, the authkey is the Rackspace Cloud API key.

Setting the optional retry_auth variable to false will cause an exception to be thrown if your authorization token expires. Otherwise, it will attempt to reauthenticate.

This will likely be the base class for most operations.

cf = CloudFiles::Connection.new(MY_USERNAME, MY_API_KEY)


57
58
59
60
61
62
63
64
# File 'lib/cloudfiles/connection.rb', line 57

def initialize(authuser,authkey,retry_auth = true) 
  @authuser = authuser
  @authkey = authkey
  @retry_auth = retry_auth
  @authok = false
  @http = {}
  CloudFiles::Authentication.new(self)
end

Instance Attribute Details

#authkeyObject (readonly)

Authentication key provided when the CloudFiles class was instantiated



7
8
9
# File 'lib/cloudfiles/connection.rb', line 7

def authkey
  @authkey
end

#authokObject

Instance variable that is set when authorization succeeds



40
41
42
# File 'lib/cloudfiles/connection.rb', line 40

def authok
  @authok
end

#authtokenObject

Token returned after a successful authentication



10
11
12
# File 'lib/cloudfiles/connection.rb', line 10

def authtoken
  @authtoken
end

#authuserObject (readonly)

Authentication username provided when the CloudFiles class was instantiated



13
14
15
# File 'lib/cloudfiles/connection.rb', line 13

def authuser
  @authuser
end

#bytesObject (readonly)

The total size in bytes under this connection



43
44
45
# File 'lib/cloudfiles/connection.rb', line 43

def bytes
  @bytes
end

#cdnmgmthostObject

Hostname of the CDN management server



16
17
18
# File 'lib/cloudfiles/connection.rb', line 16

def cdnmgmthost
  @cdnmgmthost
end

#cdnmgmtpathObject

Path for managing containers on the CDN management server



19
20
21
# File 'lib/cloudfiles/connection.rb', line 19

def cdnmgmtpath
  @cdnmgmtpath
end

#cdnmgmtportObject

Port number for the CDN server



22
23
24
# File 'lib/cloudfiles/connection.rb', line 22

def cdnmgmtport
  @cdnmgmtport
end

#cdnmgmtschemeObject

URI scheme for the CDN server



25
26
27
# File 'lib/cloudfiles/connection.rb', line 25

def cdnmgmtscheme
  @cdnmgmtscheme
end

#countObject (readonly)

The total number of containers under this connection



46
47
48
# File 'lib/cloudfiles/connection.rb', line 46

def count
  @count
end

#storagehostObject

Hostname of the storage server



28
29
30
# File 'lib/cloudfiles/connection.rb', line 28

def storagehost
  @storagehost
end

#storagepathObject

Path for managing containers/objects on the storage server



31
32
33
# File 'lib/cloudfiles/connection.rb', line 31

def storagepath
  @storagepath
end

#storageportObject

Port for managing the storage server



34
35
36
# File 'lib/cloudfiles/connection.rb', line 34

def storageport
  @storageport
end

#storageschemeObject

URI scheme for the storage server



37
38
39
# File 'lib/cloudfiles/connection.rb', line 37

def storagescheme
  @storagescheme
end

Instance Method Details

#authok?Boolean

Returns true if the authentication was successful and returns false otherwise.

cf.authok?
=> true

Returns:

  • (Boolean)


70
71
72
# File 'lib/cloudfiles/connection.rb', line 70

def authok?
  @authok
end

#cfreq(method, server, path, port, scheme, headers = {}, data = nil, attempts = 0, &block) ⇒ Object

This method actually makes the HTTP calls out to the server



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/cloudfiles/connection.rb', line 220

def cfreq(method,server,path,port,scheme,headers = {},data = nil,attempts = 0,&block) # :nodoc:
  start = Time.now
  headers['Transfer-Encoding'] = "chunked" if data.is_a?(IO)
  hdrhash = headerprep(headers)
  start_http(server,path,port,scheme,hdrhash)
  request = Net::HTTP.const_get(method.to_s.capitalize).new(path,hdrhash)
  if data
    if data.respond_to?(:read)
      request.body_stream = data
    else
      request.body = data
    end
    unless data.is_a?(IO)
      request.content_length = data.respond_to?(:lstat) ? data.stat.size : data.size
    end
  else
    request.content_length = 0
  end
  response = @http[server].request(request,&block)
  raise ExpiredAuthTokenException if response.code == "401"
  response
rescue Errno::EPIPE, Timeout::Error, Errno::EINVAL, EOFError
  # Server closed the connection, retry
  raise ConnectionException, "Unable to reconnect to #{server} after #{count} attempts" if attempts >= 5
  attempts += 1
  @http[server].finish
  start_http(server,path,port,scheme,headers)
  retry
rescue ExpiredAuthTokenException
  raise ConnectionException, "Authentication token expired and you have requested not to retry" if @retry_auth == false
  CloudFiles::Authentication.new(self)
  retry
end

#container(name) ⇒ Object Also known as: get_container

Returns an CloudFiles::Container object that can be manipulated easily. Throws a NoSuchContainerException if the container doesn’t exist.

container = cf.container('test')
container.count
=> 2


80
81
82
# File 'lib/cloudfiles/connection.rb', line 80

def container(name)
  CloudFiles::Container.new(self,name)
end

#container_exists?(containername) ⇒ Boolean

Returns true if the requested container exists and returns false otherwise.

cf.container_exists?('good_container')
=> true

cf.container_exists?('bad_container')
=> false

Returns:

  • (Boolean)


159
160
161
162
# File 'lib/cloudfiles/connection.rb', line 159

def container_exists?(containername)
  response = cfreq("HEAD",@storagehost,"#{@storagepath}/#{containername}",@storageport,@storagescheme)
  return (response.code == "204")? true : false ;
end

#containers(limit = 0, marker = "") ⇒ Object Also known as: list_containers

Gathers a list of the containers that exist for the account and returns the list of container names as an array. If no containers exist, an empty array is returned. Throws an InvalidResponseException if the request fails.

If you supply the optional limit and marker parameters, the call will return the number of containers specified in limit, starting after the object named in marker.

cf.containers
=> ["backup", "Books", "cftest", "test", "video", "webpics"] 

cf.containers(2,'cftest')
=> ["test", "video"]


112
113
114
115
116
117
118
119
120
121
# File 'lib/cloudfiles/connection.rb', line 112

def containers(limit=0,marker="")
  paramarr = []
  paramarr << ["limit=#{URI.encode(limit.to_s).gsub(/&/,'%26')}"] if limit.to_i > 0
  paramarr << ["offset=#{URI.encode(marker.to_s).gsub(/&/,'%26')}"] unless marker.to_s.empty?
  paramstr = (paramarr.size > 0)? paramarr.join("&") : "" ;
  response = cfreq("GET",@storagehost,"#{@storagepath}?#{paramstr}",@storageport,@storagescheme)
  return [] if (response.code == "204")
  raise InvalidResponseException, "Invalid response code #{response.code}" unless (response.code == "200")
  CloudFiles.lines(response.body)
end

#containers_detail(limit = 0, marker = "") ⇒ Object Also known as: list_containers_info

Retrieves a list of containers on the account along with their sizes (in bytes) and counts of the objects held within them. If no containers exist, an empty hash is returned. Throws an InvalidResponseException if the request fails.

If you supply the optional limit and marker parameters, the call will return the number of containers specified in limit, starting after the object named in marker.

cf.containers_detail              
=> { "container1" => { :bytes => "36543", :count => "146" }, 
     "container2" => { :bytes => "105943", :count => "25" } }


134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/cloudfiles/connection.rb', line 134

def containers_detail(limit=0,marker="")
  paramarr = []
  paramarr << ["limit=#{URI.encode(limit.to_s).gsub(/&/,'%26')}"] if limit.to_i > 0
  paramarr << ["offset=#{URI.encode(marker.to_s).gsub(/&/,'%26')}"] unless marker.to_s.empty?
  paramstr = (paramarr.size > 0)? paramarr.join("&") : "" ;
  response = cfreq("GET",@storagehost,"#{@storagepath}?format=xml&#{paramstr}",@storageport,@storagescheme)
  return {} if (response.code == "204")
  raise InvalidResponseException, "Invalid response code #{response.code}" unless (response.code == "200")
  doc = REXML::Document.new(response.body)
  detailhash = {}
  doc.elements.each("account/container/") { |c|
    detailhash[c.elements["name"].text] = { :bytes => c.elements["bytes"].text, :count => c.elements["count"].text  }
  }
  doc = nil
  return detailhash
end

#create_container(containername) ⇒ Object

Creates a new container and returns the CloudFiles::Container object. Throws an InvalidResponseException if the request fails.

Slash (/) and question mark (?) are invalid characters, and will be stripped out. The container name is limited to 256 characters or less.

container = cf.create_container('new_container')
container.name
=> "new_container"

container = cf.create_container('bad/name')
=> SyntaxException: Container name cannot contain the characters '/' or '?'

Raises:



176
177
178
179
180
181
182
# File 'lib/cloudfiles/connection.rb', line 176

def create_container(containername)
  raise SyntaxException, "Container name cannot contain the characters '/' or '?'" if containername.match(/[\/\?]/)
  raise SyntaxException, "Container name is limited to 256 characters" if containername.length > 256
  response = cfreq("PUT",@storagehost,"#{@storagepath}/#{containername}",@storageport,@storagescheme)
  raise InvalidResponseException, "Unable to create container #{containername}" unless (response.code == "201" || response.code == "202")
  CloudFiles::Container.new(self,containername)
end

#delete_container(containername) ⇒ Object

Deletes a container from the account. Throws a NonEmptyContainerException if the container still contains objects. Throws a NoSuchContainerException if the container doesn’t exist.

cf.delete_container('new_container')
=> true

cf.delete_container('video')
=> NonEmptyContainerException: Container video is not empty

cf.delete_container('nonexistent')
=> NoSuchContainerException: Container nonexistent does not exist


195
196
197
198
199
200
# File 'lib/cloudfiles/connection.rb', line 195

def delete_container(containername)
  response = cfreq("DELETE",@storagehost,"#{@storagepath}/#{containername}",@storageport,@storagescheme)
  raise NonEmptyContainerException, "Container #{containername} is not empty" if (response.code == "409")
  raise NoSuchContainerException, "Container #{containername} does not exist" unless (response.code == "204")
  true
end

#get_infoObject

Sets instance variables for the bytes of storage used for this account/connection, as well as the number of containers stored under the account. Returns a hash with :bytes and :count keys, and also sets the instance variables.

cf.get_info
=> {:count=>8, :bytes=>42438527}
cf.bytes
=> 42438527


92
93
94
95
96
97
98
# File 'lib/cloudfiles/connection.rb', line 92

def get_info
  response = cfreq("HEAD",@storagehost,@storagepath,@storageport,@storagescheme)
  raise InvalidResponseException, "Unable to obtain account size" unless (response.code == "204")
  @bytes = response["x-account-bytes-used"].to_i
  @count = response["x-account-container-count"].to_i
  {:bytes => @bytes, :count => @count}
end

#public_containers(enabled_only = false) ⇒ Object

Gathers a list of public (CDN-enabled) containers that exist for an account and returns the list of container names as an array. If no containers are public, an empty array is returned. Throws a InvalidResponseException if the request fails.

If you pass the optional argument as true, it will only show containers that are CURRENTLY being shared on the CDN, as opposed to the default behavior which is to show all containers that have EVER been public.

cf.public_containers
=> ["video", "webpics"]


211
212
213
214
215
216
217
# File 'lib/cloudfiles/connection.rb', line 211

def public_containers(enabled_only = false)
  paramstr = enabled_only == true ? "enabled_only=true" : ""
  response = cfreq("GET",@cdnmgmthost,"#{@cdnmgmtpath}?#{paramstr}",@cdnmgmtport,@cdnmgmtscheme)
  return [] if (response.code == "204")
  raise InvalidResponseException, "Invalid response code #{response.code}" unless (response.code == "200")
  CloudFiles.lines(response.body)
end