You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2012/11/18 02:23:01 UTC

svn commit: r1410809 [3/4] - in /libcloud/branches/0.11.x: ./ libcloud/ libcloud/common/ libcloud/compute/ libcloud/compute/drivers/ libcloud/data/ libcloud/dns/ libcloud/dns/drivers/ libcloud/loadbalancer/ libcloud/loadbalancer/drivers/ libcloud/stora...

Modified: libcloud/branches/0.11.x/libcloud/loadbalancer/drivers/rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.11.x/libcloud/loadbalancer/drivers/rackspace.py?rev=1410809&r1=1410808&r2=1410809&view=diff
==============================================================================
--- libcloud/branches/0.11.x/libcloud/loadbalancer/drivers/rackspace.py (original)
+++ libcloud/branches/0.11.x/libcloud/loadbalancer/drivers/rackspace.py Sun Nov 18 01:22:54 2012
@@ -27,13 +27,12 @@ from libcloud.loadbalancer.base import D
 from libcloud.common.types import LibcloudError
 from libcloud.common.base import JsonResponse, PollingConnection
 from libcloud.loadbalancer.types import State, MemberCondition
-from libcloud.common.openstack import OpenStackBaseConnection, OpenStackDriverMixin
-from libcloud.common.rackspace import (
-        AUTH_URL_US, AUTH_URL_UK)
+from libcloud.common.openstack import OpenStackBaseConnection,\
+    OpenStackDriverMixin
+from libcloud.common.rackspace import (AUTH_URL_US, AUTH_URL_UK)
 
 
 class RackspaceResponse(JsonResponse):
-
     def parse_body(self):
         if not self.body:
             return None
@@ -51,7 +50,7 @@ class RackspaceHealthMonitor(object):
     @type type: C{str}
 
     @param delay: minimum seconds to wait before executing the health
-                  monitor.  (Must be between 1 and 3600)
+                      monitor.  (Must be between 1 and 3600)
     @type delay: C{int}
 
     @param timeout: maximum seconds to wait when establishing a
@@ -105,8 +104,8 @@ class RackspaceHTTPHealthMonitor(Rackspa
 
     def __init__(self, type, delay, timeout, attempts_before_deactivation,
                  path, body_regex, status_regex):
-        super(RackspaceHTTPHealthMonitor, self).__init__(type, delay, timeout,
-            attempts_before_deactivation)
+        super(RackspaceHTTPHealthMonitor, self).__init__(
+            type, delay, timeout, attempts_before_deactivation)
         self.path = path
         self.body_regex = body_regex
         self.status_regex = status_regex
@@ -209,7 +208,7 @@ class RackspaceAccessRule(object):
         self.address = address
 
     def _to_dict(self):
-        type_string = \
+        type_string =\
             RackspaceAccessRuleType._RULE_TYPE_STRING_MAP[self.rule_type]
 
         as_dict = {
@@ -249,8 +248,9 @@ class RackspaceConnection(OpenStackBaseC
         if method == 'GET':
             self._add_cache_busting_to_params(params)
 
-        return super(RackspaceConnection, self).request(action=action,
-                params=params, data=data, method=method, headers=headers)
+        return super(RackspaceConnection, self).request(
+            action=action, params=params,
+            data=data, method=method, headers=headers)
 
     def get_poll_request_kwargs(self, response, context, request_kwargs):
         return {'action': request_kwargs['action'],
@@ -274,16 +274,18 @@ class RackspaceConnection(OpenStackBaseC
         if self._auth_version == "1.1":
             ep = self.service_catalog.get_endpoint(name="cloudServers")
 
-            return self._construct_loadbalancer_endpoint_from_servers_endpoint(ep)
+            return self._construct_loadbalancer_endpoint_from_servers_endpoint(
+                ep)
         elif "2.0" in self._auth_version:
             ep = self.service_catalog.get_endpoint(name="cloudServers",
-                service_type="compute",
-                region=None)
+                                                   service_type="compute",
+                                                   region=None)
 
-            return self._construct_loadbalancer_endpoint_from_servers_endpoint(ep)
+            return self._construct_loadbalancer_endpoint_from_servers_endpoint(
+                ep)
         else:
-            raise LibcloudError("Auth version %s not supported" % \
-                self._auth_version)
+            raise LibcloudError(
+                "Auth version %s not supported" % self._auth_version)
 
     def _construct_loadbalancer_endpoint_from_servers_endpoint(self, ep):
         if 'publicURL' in ep:
@@ -301,6 +303,7 @@ class RackspaceLBDriver(Driver, OpenStac
     connectionCls = RackspaceConnection
     api_name = 'rackspace_lb'
     name = 'Rackspace LB'
+    website = 'http://www.rackspace.com/'
 
     LB_STATE_MAP = {
         'ACTIVE': State.RUNNING,
@@ -343,19 +346,22 @@ class RackspaceLBDriver(Driver, OpenStac
 
     def list_protocols(self):
         return self._to_protocols(
-                   self.connection.request('/loadbalancers/protocols').object)
+            self.connection.request('/loadbalancers/protocols').object)
 
     def ex_list_protocols_with_default_ports(self):
         """
-        @rtype: C{list} of tuples of protocols (C{str}) with default ports
-        (C{int}).
+        List protocols with default ports.
+
+        @rtype: C{list} of C{tuple}
         @return: A list of protocols with default ports included.
         """
         return self._to_protocols_with_default_ports(
-                   self.connection.request('/loadbalancers/protocols').object)
+            self.connection.request('/loadbalancers/protocols').object)
 
     def list_balancers(self, ex_member_address=None):
         """
+        @inherits: L{Driver.list_balancers}
+
         @param ex_member_address: Optional IP address of the attachment member.
                                   If provided, only the load balancers which
                                   have this member attached will be returned.
@@ -367,8 +373,7 @@ class RackspaceLBDriver(Driver, OpenStac
             params['nodeaddress'] = ex_member_address
 
         return self._to_balancers(
-                self.connection.request('/loadbalancers', params=params)
-                    .object)
+            self.connection.request('/loadbalancers', params=params).object)
 
     def create_balancer(self, name, members, protocol='http',
                         port=80, algorithm=DEFAULT_ALGORITHM):
@@ -380,25 +385,27 @@ class RackspaceLBDriver(Driver, OpenStac
         """
         Creates a new load balancer instance
 
-        @keyword name: Name of the new load balancer (required)
-        @type name: C{str}
+        @param name: Name of the new load balancer (required)
+        @type  name: C{str}
 
-        @keyword members: C{list} ofL{Member}s to attach to balancer
-        @type: C{list} of L{Member}s
+        @param members: C{list} ofL{Member}s to attach to balancer
+        @type  members: C{list} of L{Member}
 
-        @keyword protocol: Loadbalancer protocol, defaults to http.
-        @type: C{str}
+        @param protocol: Loadbalancer protocol, defaults to http.
+        @type  protocol: C{str}
 
-        @keyword port: Port the load balancer should listen on, defaults to 80
-        @type port: C{str}
+        @param port: Port the load balancer should listen on, defaults to 80
+        @type  port: C{str}
 
-        @keyword algorithm: Load balancing algorithm, defaults to
+        @param algorithm: Load balancing algorithm, defaults to
                             LBAlgorithm.ROUND_ROBIN
-        @type algorithm: C{LBAlgorithm}
+        @type  algorithm: L{Algorithm}
 
-        @keyword vip: Virtual ip type of PUBLIC, SERVICENET, or ID of a virtual
+        @param vip: Virtual ip type of PUBLIC, SERVICENET, or ID of a virtual
                       ip
-        @type vip: C{str}
+        @type  vip: C{str}
+
+        @rtype: L{LoadBalancer}
         """
         balancer_attrs = self._kwargs_to_mutable_attrs(
             name=name,
@@ -409,7 +416,7 @@ class RackspaceLBDriver(Driver, OpenStac
 
         balancer_attrs.update({
             'nodes': [self._member_attributes(member) for member in members],
-            })
+        })
         balancer_object = {"loadBalancer": balancer_attrs}
 
         resp = self.connection.request('/loadbalancers',
@@ -427,8 +434,8 @@ class RackspaceLBDriver(Driver, OpenStac
         # If the condition is not specified on the member, then it should be
         # set to ENABLED by default
         if 'condition' not in member_attributes:
-            member_attributes['condition'] = \
-            self.CONDITION_LB_MEMBER_MAP[MemberCondition.ENABLED]
+            member_attributes['condition'] =\
+                self.CONDITION_LB_MEMBER_MAP[MemberCondition.ENABLED]
 
         return member_attributes
 
@@ -443,15 +450,15 @@ class RackspaceLBDriver(Driver, OpenStac
         Destroys a list of Balancers (the API supports up to 10).
 
         @param balancers: A list of Balancers to destroy.
-        @type balancers: C{list}
+        @type balancers: C{list} of L{LoadBalancer}
 
-        @rtype: C{bool}
         @return: Returns whether the destroy request was accepted.
+        @rtype: C{bool}
         """
         ids = [('id', balancer.id) for balancer in balancers]
         resp = self.connection.request('/loadbalancers',
-            method='DELETE',
-            params=ids)
+                                       method='DELETE',
+                                       params=ids)
 
         return resp.status == httplib.ACCEPTED
 
@@ -466,26 +473,28 @@ class RackspaceLBDriver(Driver, OpenStac
 
         uri = '/loadbalancers/%s/nodes' % (balancer.id)
         resp = self.connection.request(uri, method='POST',
-                data=json.dumps(member_object))
-        return self._to_members(resp.object)[0]
+                                       data=json.dumps(member_object))
+        return self._to_members(resp.object, balancer)[0]
 
     def ex_balancer_attach_members(self, balancer, members):
         """
         Attaches a list of members to a load balancer.
 
         @param balancer: The Balancer to which members will be attached.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param members: A list of Members to attach.
-        @type members: C{list}
+        @type  members: C{list} of L{Member}
+
+        @rtype: C{list} of L{Member}
         """
         member_objects = {"nodes": [self._member_attributes(member) for member
                                     in members]}
 
         uri = '/loadbalancers/%s/nodes' % (balancer.id)
         resp = self.connection.request(uri, method='POST',
-                data=json.dumps(member_objects))
-        return self._to_members(resp.object)
+                                       data=json.dumps(member_objects))
+        return self._to_members(resp.object, balancer)
 
     def balancer_detach_member(self, balancer, member):
         # Loadbalancer always needs to have at least 1 member.
@@ -503,13 +512,13 @@ class RackspaceLBDriver(Driver, OpenStac
         balancer is in a RUNNING state again.
 
         @param balancer: The Balancer to detach members from.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param members: A list of Members to detach.
-        @type members: C{list}
+        @type  members: C{list} of L{Member}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         accepted = self.ex_balancer_detach_members_no_poll(balancer, members)
 
@@ -525,13 +534,13 @@ class RackspaceLBDriver(Driver, OpenStac
         This method returns immediately.
 
         @param balancer: The Balancer to detach members from.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param members: A list of Members to detach.
-        @type members: C{list}
+        @type  members: C{list} of L{Member}
 
-        @rtype: C{bool}
         @return: Returns whether the detach request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/nodes' % (balancer.id)
         ids = [('id', member.id) for member in members]
@@ -541,23 +550,28 @@ class RackspaceLBDriver(Driver, OpenStac
 
     def balancer_list_members(self, balancer):
         uri = '/loadbalancers/%s/nodes' % (balancer.id)
-        return self._to_members(
-                self.connection.request(uri).object)
+        data = self.connection.request(uri).object
+        return self._to_members(data, balancer)
 
     def update_balancer(self, balancer, **kwargs):
         attrs = self._kwargs_to_mutable_attrs(**kwargs)
         resp = self.connection.async_request(
-                    action='/loadbalancers/%s' % balancer.id,
-                    method='PUT',
-                    data=json.dumps(attrs))
+            action='/loadbalancers/%s' % balancer.id,
+            method='PUT',
+            data=json.dumps(attrs))
         return self._to_balancer(resp.object["loadBalancer"])
 
     def ex_update_balancer_no_poll(self, balancer, **kwargs):
+        """
+        Update balancer no poll.
+
+        @inherits: L{Driver.update_balancer}
+        """
         attrs = self._kwargs_to_mutable_attrs(**kwargs)
         resp = self.connection.request(
-                    action='/loadbalancers/%s' % balancer.id,
-                    method='PUT',
-                    data=json.dumps(attrs))
+            action='/loadbalancers/%s' % balancer.id,
+            method='PUT',
+            data=json.dumps(attrs))
         return resp.status == httplib.ACCEPTED
 
     def ex_balancer_update_member(self, balancer, member, **kwargs):
@@ -568,17 +582,20 @@ class RackspaceLBDriver(Driver, OpenStac
         again.
 
         @param balancer: Balancer to update the member on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
+
+        @param member: Member which should be used
+        @type member: L{Member}
 
-        @param **kwargs: New attributes.  Should contain either 'weight'
+        @keyword **kwargs: New attributes.  Should contain either 'weight'
         or 'condition'.  'condition' can be set to 'ENABLED', 'DISABLED'.
         or 'DRAINING'.  'weight' can be set to a positive integer between
         1 and 100, with a higher weight indicating that the node will receive
         more traffic (assuming the Balancer is using a weighted algorithm).
         @type **kwargs: C{dict}
 
-        @rtype: C{Member}
         @return: Updated Member.
+        @rtype: L{Member}
         """
         accepted = self.ex_balancer_update_member_no_poll(
             balancer, member, **kwargs)
@@ -603,17 +620,20 @@ class RackspaceLBDriver(Driver, OpenStac
         include 'weight' or 'condition'.  This method returns immediately.
 
         @param balancer: Balancer to update the member on.
-        @type balancer: C{Balancer}
+        @type balancer: L{LoadBalancer}
 
-        @param **kwargs: New attributes.  Should contain either 'weight'
+        @param member: Member which should be used
+        @type member: L{Member}
+
+        @keyword **kwargs: New attributes.  Should contain either 'weight'
         or 'condition'.  'condition' can be set to 'ENABLED', 'DISABLED'.
         or 'DRAINING'.  'weight' can be set to a positive integer between
         1 and 100, with a higher weight indicating that the node will receive
         more traffic (assuming the Balancer is using a weighted algorithm).
         @type **kwargs: C{dict}
 
-        @rtype: C{bool}
         @return: Returns whether the update request was accepted.
+        @rtype: C{bool}
         """
         resp = self.connection.request(
             action='/loadbalancers/%s/nodes/%s' % (balancer.id, member.id),
@@ -627,17 +647,35 @@ class RackspaceLBDriver(Driver, OpenStac
         """
         Lists algorithms supported by the API.  Returned as strings because
         this list may change in the future.
+
+        @rtype: C{list} of C{str}
         """
         response = self.connection.request('/loadbalancers/algorithms')
         return [a["name"].upper() for a in response.object["algorithms"]]
 
     def ex_get_balancer_error_page(self, balancer):
+        """
+        List error page configured for the specified load balancer.
+
+        @param balancer: Balancer which should be used
+        @type balancer: L{LoadBalancer}
+
+        @rtype: C{str}
+        """
         uri = '/loadbalancers/%s/errorpage' % (balancer.id)
         resp = self.connection.request(uri)
 
         return resp.object["errorpage"]["content"]
 
     def ex_balancer_access_list(self, balancer):
+        """
+        List the access list.
+
+        @param balancer: Balancer which should be used
+        @type balancer: L{LoadBalancer}
+
+        @rtype: C{list} of L{RackspaceAccessRule}
+        """
         uri = '/loadbalancers/%s/accesslist' % (balancer.id)
         resp = self.connection.request(uri)
 
@@ -663,16 +701,16 @@ class RackspaceLBDriver(Driver, OpenStac
         again.
 
         @param balancer: Balancer to update.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param health_monitor: Health Monitor for the balancer.
-        @type health_monitor: C{RackspaceHealthMonitor}
+        @type  health_monitor: L{RackspaceHealthMonitor}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
-        accepted = self.ex_update_balancer_health_monitor_no_poll(balancer,
-                    health_monitor)
+        accepted = self.ex_update_balancer_health_monitor_no_poll(
+            balancer, health_monitor)
         if not accepted:
             msg = 'Update health monitor request not accepted'
             raise LibcloudError(msg, driver=self)
@@ -685,19 +723,18 @@ class RackspaceLBDriver(Driver, OpenStac
         Sets a Balancer's health monitor.  This method returns immediately.
 
         @param balancer: Balancer to update health monitor on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param health_monitor: Health Monitor for the balancer.
-        @type health_monitor: C{RackspaceHealthMonitor}
+        @type  health_monitor: L{RackspaceHealthMonitor}
 
-        @rtype: C{bool}
         @return: Returns whether the update request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/healthmonitor' % (balancer.id)
 
-        resp = self.connection.request(uri,
-            method='PUT',
-            data=json.dumps(health_monitor._to_dict()))
+        resp = self.connection.request(
+            uri, method='PUT', data=json.dumps(health_monitor._to_dict()))
 
         return resp.status == httplib.ACCEPTED
 
@@ -708,10 +745,10 @@ class RackspaceLBDriver(Driver, OpenStac
         state again.
 
         @param balancer: Balancer to disable health monitor on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         if not self.ex_disable_balancer_health_monitor_no_poll(balancer):
             msg = 'Disable health monitor request not accepted'
@@ -725,15 +762,15 @@ class RackspaceLBDriver(Driver, OpenStac
         immediately.
 
         @param balancer: Balancer to disable health monitor on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{bool}
         @return: Returns whether the disable request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/healthmonitor' % (balancer.id)
 
         resp = self.connection.request(uri,
-            method='DELETE')
+                                       method='DELETE')
 
         return resp.status == httplib.ACCEPTED
 
@@ -745,13 +782,13 @@ class RackspaceLBDriver(Driver, OpenStac
         RUNNING state again.
 
         @param balancer: Balancer to update connection throttle on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param connection_throttle: Connection Throttle for the balancer.
-        @type connection_throttle: C{RackspaceConnectionThrottle}
+        @type  connection_throttle: L{RackspaceConnectionThrottle}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         accepted = self.ex_update_balancer_connection_throttle_no_poll(
             balancer, connection_throttle)
@@ -769,16 +806,17 @@ class RackspaceLBDriver(Driver, OpenStac
         immediately.
 
         @param balancer: Balancer to update connection throttle on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param connection_throttle: Connection Throttle for the balancer.
-        @type connection_throttle: C{RackspaceConnectionThrottle}
+        @type  connection_throttle: L{RackspaceConnectionThrottle}
 
-        @rtype: C{bool}
         @return: Returns whether the update request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/connectionthrottle' % (balancer.id)
-        resp = self.connection.request(uri, method='PUT',
+        resp = self.connection.request(
+            uri, method='PUT',
             data=json.dumps(connection_throttle._to_dict()))
 
         return resp.status == httplib.ACCEPTED
@@ -790,10 +828,10 @@ class RackspaceLBDriver(Driver, OpenStac
         state again.
 
         @param balancer: Balancer to disable connection throttle on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         if not self.ex_disable_balancer_connection_throttle_no_poll(balancer):
             msg = 'Disable connection throttle request not accepted'
@@ -807,10 +845,10 @@ class RackspaceLBDriver(Driver, OpenStac
         immediately.
 
         @param balancer: Balancer to disable connection throttle on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{bool}
         @return: Returns whether the disable request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/connectionthrottle' % (balancer.id)
         resp = self.connection.request(uri, method='DELETE')
@@ -824,10 +862,10 @@ class RackspaceLBDriver(Driver, OpenStac
         state again.
 
         @param balancer: Balancer to enable connection logging on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         if not self.ex_enable_balancer_connection_logging_no_poll(balancer):
             msg = 'Enable connection logging request not accepted'
@@ -841,19 +879,17 @@ class RackspaceLBDriver(Driver, OpenStac
         immediately.
 
         @param balancer: Balancer to enable connection logging on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{bool}
         @return: Returns whether the enable request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/connectionlogging' % (balancer.id)
 
-        resp = self.connection.request(uri, method='PUT',
-            data=json.dumps({
-            'connectionLogging': {
-                'enabled': True
-            }
-        }))
+        resp = self.connection.request(
+            uri, method='PUT',
+            data=json.dumps({'connectionLogging': {'enabled': True}})
+        )
 
         return resp.status == httplib.ACCEPTED
 
@@ -864,10 +900,10 @@ class RackspaceLBDriver(Driver, OpenStac
         state again.
 
         @param balancer: Balancer to disable connection logging on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         if not self.ex_disable_balancer_connection_logging_no_poll(balancer):
             msg = 'Disable connection logging request not accepted'
@@ -881,18 +917,16 @@ class RackspaceLBDriver(Driver, OpenStac
         immediately.
 
         @param balancer: Balancer to disable connection logging on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{bool}
         @return: Returns whether the disable request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/connectionlogging' % (balancer.id)
-        resp = self.connection.request(uri, method='PUT',
-            data=json.dumps({
-            'connectionLogging': {
-                'enabled': False
-            }
-        }))
+        resp = self.connection.request(
+            uri, method='PUT',
+            data=json.dumps({'connectionLogging': {'enabled': False}})
+        )
 
         return resp.status == httplib.ACCEPTED
 
@@ -903,10 +937,10 @@ class RackspaceLBDriver(Driver, OpenStac
         has been processed and the balancer is in a RUNNING state again.
 
         @param balancer: Balancer to enable session persistence on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         if not self.ex_enable_balancer_session_persistence_no_poll(balancer):
             msg = 'Enable session persistence request not accepted'
@@ -920,18 +954,17 @@ class RackspaceLBDriver(Driver, OpenStac
         type to 'HTTP_COOKIE'.  This method returns immediately.
 
         @param balancer: Balancer to enable session persistence on.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{bool}
         @return: Returns whether the enable request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/sessionpersistence' % (balancer.id)
-        resp = self.connection.request(uri, method='PUT',
-            data=json.dumps({
-                'sessionPersistence': {
-                    'persistenceType': 'HTTP_COOKIE'
-                }
-            }))
+        resp = self.connection.request(
+            uri, method='PUT',
+            data=json.dumps(
+                {'sessionPersistence': {'persistenceType': 'HTTP_COOKIE'}})
+        )
 
         return resp.status == httplib.ACCEPTED
 
@@ -942,10 +975,10 @@ class RackspaceLBDriver(Driver, OpenStac
         state again.
 
         @param balancer: Balancer to disable session persistence on.
-        @type balancer: C{Balancer}
+        @type balancer:  L{LoadBalancer}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         if not self.ex_disable_balancer_session_persistence_no_poll(balancer):
             msg = 'Disable session persistence request not accepted'
@@ -959,10 +992,10 @@ class RackspaceLBDriver(Driver, OpenStac
         immediately.
 
         @param balancer: Balancer to disable session persistence for.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{bool}
         @return: Returns whether the disable request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/sessionpersistence' % (balancer.id)
         resp = self.connection.request(uri, method='DELETE')
@@ -976,13 +1009,13 @@ class RackspaceLBDriver(Driver, OpenStac
         RUNNING state again.
 
         @param balancer: Balancer to update the custom error page for.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param page_content: HTML content for the custom error page.
-        @type page_content: C{string}
+        @type  page_content: C{str}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype:  L{LoadBalancer}
         """
         accepted = self.ex_update_balancer_error_page_no_poll(balancer,
                                                               page_content)
@@ -998,21 +1031,19 @@ class RackspaceLBDriver(Driver, OpenStac
         immediately.
 
         @param balancer: Balancer to update the custom error page for.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param page_content: HTML content for the custom error page.
-        @type page_content: C{string}
+        @type  page_content: C{str}
 
-        @rtype: C{bool}
         @return: Returns whether the update request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/errorpage' % (balancer.id)
-        resp = self.connection.request(uri, method='PUT',
-            data=json.dumps({
-                'errorpage': {
-                    'content': page_content
-                }
-            }))
+        resp = self.connection.request(
+            uri, method='PUT',
+            data=json.dumps({'errorpage': {'content': page_content}})
+        )
 
         return resp.status == httplib.ACCEPTED
 
@@ -1024,10 +1055,10 @@ class RackspaceLBDriver(Driver, OpenStac
         again.
 
         @param balancer: Balancer to disable the custom error page for.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         if not self.ex_disable_balancer_custom_error_page_no_poll(balancer):
             msg = 'Disable custom error page request not accepted'
@@ -1041,10 +1072,10 @@ class RackspaceLBDriver(Driver, OpenStac
         the Rackspace-provided default.  This method returns immediately.
 
         @param balancer: Balancer to disable the custom error page for.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @rtype: C{bool}
         @return: Returns whether the disable request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/errorpage' % (balancer.id)
         resp = self.connection.request(uri, method='DELETE')
@@ -1060,13 +1091,13 @@ class RackspaceLBDriver(Driver, OpenStac
         RUNNING state again.
 
         @param balancer: Balancer to create the access rule for.
-        @type balancer: C{Balancer}
+        @type balancer: L{LoadBalancer}
 
         @param rule: Access Rule to add to the balancer.
-        @type rule: C{RackspaceAccessRule}
+        @type rule: L{RackspaceAccessRule}
 
-        @rtype: C{RackspaceAccessRule}
         @return: The created access rule.
+        @rtype: L{RackspaceAccessRule}
         """
         accepted = self.ex_create_balancer_access_rule_no_poll(balancer, rule)
         if not accepted:
@@ -1089,19 +1120,19 @@ class RackspaceLBDriver(Driver, OpenStac
         immediately.
 
         @param balancer: Balancer to create the access rule for.
-        @type balancer: C{Balancer}
+        @type balancer: L{LoadBalancer}
 
         @param rule: Access Rule to add to the balancer.
-        @type rule: C{RackspaceAccessRule}
+        @type rule: L{RackspaceAccessRule}
 
-        @rtype: C{bool}
         @return: Returns whether the create request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/accesslist' % (balancer.id)
-        resp = self.connection.request(uri, method='POST',
-            data=json.dumps({
-                'networkItem': rule._to_dict()
-            }))
+        resp = self.connection.request(
+            uri, method='POST',
+            data=json.dumps({'networkItem': rule._to_dict()})
+        )
 
         return resp.status == httplib.ACCEPTED
 
@@ -1112,15 +1143,16 @@ class RackspaceLBDriver(Driver, OpenStac
         in a RUNNING state again.
 
         @param balancer: Balancer to create the access rule for.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @param rules: List of C{RackspaceAccessRule} to add to the balancer.
-        @type rules: C{list}
+        @param rules: List of L{RackspaceAccessRule} to add to the balancer.
+        @type  rules: C{list} of L{RackspaceAccessRule}
 
-        @rtype: C{RackspaceAccessRule}
         @return: The created access rules.
+        @rtype: L{RackspaceAccessRule}
         """
-        accepted = self.ex_create_balancer_access_rules_no_poll(balancer, rules)
+        accepted = self.ex_create_balancer_access_rules_no_poll(balancer,
+                                                                rules)
         if not accepted:
             msg = 'Create access rules not accepted'
             raise LibcloudError(msg, driver=self)
@@ -1147,8 +1179,8 @@ class RackspaceLBDriver(Driver, OpenStac
         enforces rule type and address uniqueness.
         """
         for r in access_list:
-            if rule_to_find.rule_type == r.rule_type and \
-               rule_to_find.address == r.address:
+            if rule_to_find.rule_type == r.rule_type and\
+                    rule_to_find.address == r.address:
                 return r
 
         return None
@@ -1159,19 +1191,20 @@ class RackspaceLBDriver(Driver, OpenStac
         returns immediately.
 
         @param balancer: Balancer to create the access rule for.
-        @type balancer: C{Balancer}
+        @type balancer: L{LoadBalancer}
 
-        @param rules: List of C{RackspaceAccessRule} to add to the balancer.
-        @type rules: C{list}
+        @param rules: List of L{RackspaceAccessRule} to add to the balancer.
+        @type  rules: C{list} of L{RackspaceAccessRule}
 
-        @rtype: C{bool}
         @return: Returns whether the create request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/accesslist' % (balancer.id)
-        resp = self.connection.request(uri, method='POST',
-            data=json.dumps({
-                'accessList' : [rule._to_dict() for rule in rules]
-            }))
+        resp = self.connection.request(
+            uri, method='POST',
+            data=json.dumps({'accessList':
+                             [rule._to_dict() for rule in rules]})
+        )
 
         return resp.status == httplib.ACCEPTED
 
@@ -1182,13 +1215,13 @@ class RackspaceLBDriver(Driver, OpenStac
         is in a RUNNING state again.
 
         @param balancer: Balancer to remove the access rule from.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param rule: Access Rule to remove from the balancer.
-        @type rule: C{RackspaceAccessRule}
+        @type  rule: L{RackspaceAccessRule}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         accepted = self.ex_destroy_balancer_access_rule_no_poll(balancer, rule)
         if not accepted:
@@ -1203,13 +1236,13 @@ class RackspaceLBDriver(Driver, OpenStac
         returns immediately.
 
         @param balancer: Balancer to remove the access rule from.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
         @param rule: Access Rule to remove from the balancer.
-        @type rule: C{RackspaceAccessRule}
+        @type  rule: L{RackspaceAccessRule}
 
-        @rtype: C{bool}
         @return: Returns whether the destroy request was accepted.
+        @rtype: C{bool}
         """
         uri = '/loadbalancers/%s/accesslist/%s' % (balancer.id, rule.id)
         resp = self.connection.request(uri, method='DELETE')
@@ -1223,14 +1256,14 @@ class RackspaceLBDriver(Driver, OpenStac
         balancer is in a RUNNING state again.
 
         @param balancer: Balancer to remove the access rules from.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @param rules: List of C{RackspaceAccessRule} objects to remove from the
-        balancer.
-        @type rules: C{list}
+        @param rules: List of L{RackspaceAccessRule} objects to remove from the
+                       balancer.
+        @type  rules: C{list} of L{RackspaceAccessRule}
 
-        @rtype: C{Balancer}
         @return: Updated Balancer.
+        @rtype: L{LoadBalancer}
         """
         accepted = self.ex_destroy_balancer_access_rules_no_poll(
             balancer, rules)
@@ -1247,21 +1280,21 @@ class RackspaceLBDriver(Driver, OpenStac
         method returns immediately.
 
         @param balancer: Balancer to remove the access rules from.
-        @type balancer: C{Balancer}
+        @type  balancer: L{LoadBalancer}
 
-        @param rules: List of C{RackspaceAccessRule} objects to remove from the
-        balancer.
-        @type rules: C{list}
+        @param rules: List of L{RackspaceAccessRule} objects to remove from the
+                            balancer.
+        @type  rules: C{list} of L{RackspaceAccessRule}
 
-        @rtype: C{bool}
         @return: Returns whether the destroy request was accepted.
+        @rtype: C{bool}
         """
         ids = [('id', rule.id) for rule in rules]
         uri = '/loadbalancers/%s/accesslist' % balancer.id
 
         resp = self.connection.request(uri,
-            method='DELETE',
-            params=ids)
+                                       method='DELETE',
+                                       params=ids)
 
         return resp.status == httplib.ACCEPTED
 
@@ -1307,8 +1340,8 @@ class RackspaceLBDriver(Driver, OpenStac
         if 'protocol' in el:
             extra['protocol'] = el['protocol']
 
-        if 'algorithm' in el and el["algorithm"] in \
-            self._VALUE_TO_ALGORITHM_MAP:
+        if 'algorithm' in el and \
+           el["algorithm"] in self._VALUE_TO_ALGORITHM_MAP:
             extra["algorithm"] = self._value_to_algorithm(el["algorithm"])
 
         if 'healthMonitor' in el:
@@ -1321,8 +1354,8 @@ class RackspaceLBDriver(Driver, OpenStac
 
         if 'sessionPersistence' in el:
             persistence = el["sessionPersistence"]
-            extra["sessionPersistenceType"] = \
-                    persistence.get("persistenceType")
+            extra["sessionPersistenceType"] =\
+                persistence.get("persistenceType")
 
         if 'connectionLogging' in el:
             logging = el["connectionLogging"]
@@ -1338,38 +1371,39 @@ class RackspaceLBDriver(Driver, OpenStac
             extra['updated'] = self._iso_to_datetime(el['updated']['time'])
 
         if 'accessList' in el:
-            extra['accessList'] = [self._to_access_rule(rule) \
+            extra['accessList'] = [self._to_access_rule(rule)
                                    for rule in el['accessList']]
 
         return LoadBalancer(id=el["id"],
-                name=el["name"],
-                state=self.LB_STATE_MAP.get(
-                    el["status"], State.UNKNOWN),
-                ip=ip,
-                port=port,
-                driver=self.connection.driver,
-                extra=extra)
+                            name=el["name"],
+                            state=self.LB_STATE_MAP.get(
+                                el["status"], State.UNKNOWN),
+                            ip=ip,
+                            port=port,
+                            driver=self.connection.driver,
+                            extra=extra)
 
-    def _to_members(self, object):
-        return [self._to_member(el) for el in object["nodes"]]
+    def _to_members(self, object, balancer=None):
+        return [self._to_member(el, balancer) for el in object["nodes"]]
 
-    def _to_member(self, el):
+    def _to_member(self, el, balancer=None):
         extra = {}
         if 'weight' in el:
             extra['weight'] = el["weight"]
 
-        if 'condition' in el and el['condition'] in \
-           self.LB_MEMBER_CONDITION_MAP:
-            extra['condition'] = \
-                    self.LB_MEMBER_CONDITION_MAP.get(el["condition"])
+        if 'condition' in el and\
+           el['condition'] in self.LB_MEMBER_CONDITION_MAP:
+            extra['condition'] =\
+                self.LB_MEMBER_CONDITION_MAP.get(el["condition"])
 
         if 'status' in el:
             extra['status'] = el["status"]
 
         lbmember = Member(id=el["id"],
-                ip=el["address"],
-                port=el["port"],
-                extra=extra)
+                          ip=el["address"],
+                          port=el["port"],
+                          balancer=balancer,
+                          extra=extra)
         return lbmember
 
     def _protocol_to_value(self, protocol):
@@ -1394,7 +1428,7 @@ class RackspaceLBDriver(Driver, OpenStac
             update_attrs['algorithm'] = algorithm_value
 
         if "protocol" in attrs:
-            update_attrs['protocol'] = \
+            update_attrs['protocol'] =\
                 self._protocol_to_value(attrs['protocol'])
 
         if "port" in attrs:
@@ -1411,7 +1445,7 @@ class RackspaceLBDriver(Driver, OpenStac
     def _kwargs_to_mutable_member_attrs(self, **attrs):
         update_attrs = {}
         if 'condition' in attrs:
-            update_attrs['condition'] = \
+            update_attrs['condition'] =\
                 self.CONDITION_LB_MEMBER_MAP.get(attrs['condition'])
 
         if 'weight' in attrs:
@@ -1425,17 +1459,17 @@ class RackspaceLBDriver(Driver, OpenStac
         type = health_monitor_data.get("type")
         delay = health_monitor_data.get("delay")
         timeout = health_monitor_data.get("timeout")
-        attempts_before_deactivation = \
-                health_monitor_data.get("attemptsBeforeDeactivation")
+        attempts_before_deactivation =\
+            health_monitor_data.get("attemptsBeforeDeactivation")
 
         if type == "CONNECT":
-            return RackspaceHealthMonitor(type=type, delay=delay,
-                timeout=timeout,
+            return RackspaceHealthMonitor(
+                type=type, delay=delay, timeout=timeout,
                 attempts_before_deactivation=attempts_before_deactivation)
 
         if type == "HTTP" or type == "HTTPS":
-            return RackspaceHTTPHealthMonitor(type=type, delay=delay,
-                timeout=timeout,
+            return RackspaceHTTPHealthMonitor(
+                type=type, delay=delay, timeout=timeout,
                 attempts_before_deactivation=attempts_before_deactivation,
                 path=health_monitor_data.get("path"),
                 status_regex=health_monitor_data.get("statusRegex"),
@@ -1451,13 +1485,15 @@ class RackspaceLBDriver(Driver, OpenStac
         max_connection_rate = connection_throttle_data.get("maxConnectionRate")
         rate_interval = connection_throttle_data.get("rateInterval")
 
-        return RackspaceConnectionThrottle(min_connections=min_connections,
+        return RackspaceConnectionThrottle(
+            min_connections=min_connections,
             max_connections=max_connections,
             max_connection_rate=max_connection_rate,
             rate_interval_seconds=rate_interval)
 
     def _to_access_rule(self, el):
-        return RackspaceAccessRule(id=el.get("id"),
+        return RackspaceAccessRule(
+            id=el.get("id"),
             rule_type=self._to_access_rule_type(el.get("type")),
             address=el.get("address"))
 

Modified: libcloud/branches/0.11.x/libcloud/loadbalancer/providers.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.11.x/libcloud/loadbalancer/providers.py?rev=1410809&r1=1410808&r2=1410809&view=diff
==============================================================================
--- libcloud/branches/0.11.x/libcloud/loadbalancer/providers.py (original)
+++ libcloud/branches/0.11.x/libcloud/loadbalancer/providers.py Sun Nov 18 01:22:54 2012
@@ -17,10 +17,10 @@ from libcloud.utils.misc import get_driv
 from libcloud.loadbalancer.types import Provider
 
 __all__ = [
-        "Provider",
-        "DRIVERS",
-        "get_driver",
-        ]
+    "Provider",
+    "DRIVERS",
+    "get_driver",
+]
 
 DRIVERS = {
         Provider.RACKSPACE_US:

Modified: libcloud/branches/0.11.x/libcloud/loadbalancer/types.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.11.x/libcloud/loadbalancer/types.py?rev=1410809&r1=1410808&r2=1410809&view=diff
==============================================================================
--- libcloud/branches/0.11.x/libcloud/loadbalancer/types.py (original)
+++ libcloud/branches/0.11.x/libcloud/loadbalancer/types.py Sun Nov 18 01:22:54 2012
@@ -14,11 +14,11 @@
 # limitations under the License.
 
 __all__ = [
-        "Provider",
-        "State",
-        "LibcloudLBError",
-        "LibcloudLBImmutableError",
-        ]
+    "Provider",
+    "State",
+    "LibcloudLBError",
+    "LibcloudLBImmutableError",
+]
 
 from libcloud.common.types import LibcloudError
 
@@ -53,9 +53,10 @@ class State(object):
     ERROR = 3
     DELETED = 4
 
+
 class MemberCondition(object):
     """
-    Each member of a load balancer can have an associated condition 
+    Each member of a load balancer can have an associated condition
     which determines its role within the load balancer.
     """
     ENABLED = 0

Modified: libcloud/branches/0.11.x/libcloud/security.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.11.x/libcloud/security.py?rev=1410809&r1=1410808&r2=1410809&view=diff
==============================================================================
--- libcloud/branches/0.11.x/libcloud/security.py (original)
+++ libcloud/branches/0.11.x/libcloud/security.py Sun Nov 18 01:22:54 2012
@@ -48,7 +48,9 @@ CA_CERTS_UNAVAILABLE_WARNING_MSG = (
 )
 
 CA_CERTS_UNAVAILABLE_ERROR_MSG = (
-    'No CA Certificates were found in CA_CERTS_PATH. '
+    'No CA Certificates were found in CA_CERTS_PATH. For information on' + \
+    ' how to get required certificate files, please visit ' + \
+    ' http://libcloud.apache.org/docs/ssl-certificate-validation.html'
 )
 
 VERIFY_SSL_DISABLED_MSG = (

Modified: libcloud/branches/0.11.x/libcloud/storage/base.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.11.x/libcloud/storage/base.py?rev=1410809&r1=1410808&r2=1410809&view=diff
==============================================================================
--- libcloud/branches/0.11.x/libcloud/storage/base.py (original)
+++ libcloud/branches/0.11.x/libcloud/storage/base.py Sun Nov 18 01:22:54 2012
@@ -35,6 +35,7 @@ from libcloud.storage.types import Objec
 
 CHUNK_SIZE = 8096
 
+
 class Object(object):
     """
     Represents an object (BLOB).
@@ -43,26 +44,26 @@ class Object(object):
     def __init__(self, name, size, hash, extra, meta_data, container,
                  driver):
         """
-        @type name: C{str}
         @param name: Object name (must be unique per container).
+        @type  name: C{str}
 
-        @type size: C{int}
         @param size: Object size in bytes.
+        @type  size: C{int}
 
-        @type hash: C{string}
         @param hash Object hash.
+        @type  hash: C{str}
 
-        @type container: C{Container}
         @param container: Object container.
+        @type  container: L{Container}
 
-        @type extra: C{dict}
         @param extra: Extra attributes.
+        @type  extra: C{dict}
 
-        @type meta_data: C{dict}
         @param meta_data: Optional object meta data.
+        @type  meta_data: C{dict}
 
-        @type driver: C{StorageDriver}
         @param driver: StorageDriver instance.
+        @type  driver: L{StorageDriver}
         """
 
         self.name = name
@@ -95,6 +96,7 @@ class Object(object):
         return ('<Object: name=%s, size=%s, hash=%s, provider=%s ...>' %
                 (self.name, self.size, self.hash, self.driver.name))
 
+
 class Container(object):
     """
     Represents a container (bucket) which can hold multiple objects.
@@ -102,14 +104,14 @@ class Container(object):
 
     def __init__(self, name, extra, driver):
         """
-        @type name: C{str}
         @param name: Container name (must be unique).
+        @type name: C{str}
 
-        @type extra: C{dict}
         @param extra: Extra attributes.
+        @type extra: C{dict}
 
-        @type driver: C{StorageDriver}
         @param driver: StorageDriver instance.
+        @type driver: L{StorageDriver}
         """
 
         self.name = name
@@ -156,6 +158,7 @@ class Container(object):
         return ('<Container: name=%s, provider=%s>'
                 % (self.name, self.driver.name))
 
+
 class StorageDriver(BaseDriver):
     """
     A base StorageDriver to derive from.
@@ -166,15 +169,18 @@ class StorageDriver(BaseDriver):
     hash_type = 'md5'
     supports_chunked_encoding = False
 
-    def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs):
-      super(StorageDriver, self).__init__(key=key, secret=secret, secure=secure,
-                                          host=host, port=port, **kwargs)
+    def __init__(self, key, secret=None, secure=True, host=None, port=None,
+                 **kwargs):
+        super(StorageDriver, self).__init__(key=key, secret=secret,
+                                            secure=secure, host=host,
+                                            port=port, **kwargs)
 
     def list_containers(self):
         """
         Return a list of containers.
 
         @return: A list of Container instances.
+        @rtype: C{list} of L{Container}
         """
         raise NotImplementedError(
             'list_containers not implemented for this driver')
@@ -183,10 +189,11 @@ class StorageDriver(BaseDriver):
         """
         Return a list of objects for the given container.
 
-        @type container: C{Container}
         @param container: Container instance
+        @type container: L{Container}
 
         @return: A list of Object instances.
+        @rtype: C{list} of L{Object}
         """
         raise NotImplementedError(
             'list_objects not implemented for this driver')
@@ -195,10 +202,11 @@ class StorageDriver(BaseDriver):
         """
         Return a container instance.
 
-        @type container_name: C{str}
         @param container_name: Container name.
+        @type container_name: C{str}
 
-        @return: C{Container} instance.
+        @return: L{Container} instance.
+        @rtype: L{Container}
         """
         raise NotImplementedError(
             'get_object not implemented for this driver')
@@ -207,10 +215,11 @@ class StorageDriver(BaseDriver):
         """
         Return a container CDN URL.
 
-        @type container: C{Container}
         @param container: Container instance
+        @type  container: L{Container}
 
         @return: A CDN URL for this container.
+        @rtype: C{str}
         """
         raise NotImplementedError(
             'get_container_cdn_url not implemented for this driver')
@@ -219,58 +228,78 @@ class StorageDriver(BaseDriver):
         """
         Return an object instance.
 
-        @type container_name: C{str}
         @param container_name: Container name.
+        @type  container_name: C{str}
 
-        @type object_name: C{str}
         @param object_name: Object name.
+        @type  object_name: C{str}
 
-        @return: C{Object} instance.
+        @return: L{Object} instance.
+        @rtype: L{Object}
         """
         raise NotImplementedError(
             'get_object not implemented for this driver')
 
     def get_object_cdn_url(self, obj):
         """
-        Return a container CDN URL.
+        Return a object CDN URL.
 
-        @type obj: C{Object}
         @param obj: Object instance
+        @type  obj: L{Object}
 
         @return: A CDN URL for this object.
+        @rtype: C{str}
         """
         raise NotImplementedError(
             'get_object_cdn_url not implemented for this driver')
 
     def enable_container_cdn(self, container):
+        """
+        Enable container CDN.
+
+        @param container: Container instance
+        @type  container: L{Container}
+
+        @rtype: C{bool}
+        """
         raise NotImplementedError(
             'enable_container_cdn not implemented for this driver')
 
     def enable_object_cdn(self, obj):
+        """
+        Enable object CDN.
+
+        @param obj: Object instance
+        @type  obj: L{Object}
+
+        @rtype: C{bool}
+        """
         raise NotImplementedError(
             'enable_object_cdn not implemented for this driver')
 
-    def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True):
+    def download_object(self, obj, destination_path, overwrite_existing=False,
+                        delete_on_failure=True):
         """
         Download an object to the specified destination path.
 
-        @type obj: C{Object}
         @param obj: Object instance.
+        @type obj: L{Object}
 
-        @type destination_path: C{str}
         @param destination_path: Full path to a file or a directory where the
                                 incoming file will be saved.
+        @type destination_path: C{str}
 
+        @param overwrite_existing: True to overwrite an existing file,
+            defaults to False.
         @type overwrite_existing: C{bool}
-        @param overwrite_existing: True to overwrite an existing file, defaults to False.
 
-        @type delete_on_failure: C{bool}
         @param delete_on_failure: True to delete a partially downloaded file if
         the download was not successful (hash mismatch / file size).
+        @type delete_on_failure: C{bool}
 
-        @rtype: C{bool}
         @return: True if an object has been successfully downloaded, False
         otherwise.
+        @rtype: C{bool}
         """
         raise NotImplementedError(
             'download_object not implemented for this driver')
@@ -279,11 +308,13 @@ class StorageDriver(BaseDriver):
         """
         Return a generator which yields object data.
 
-        @type obj: C{Object}
         @param obj: Object instance
+        @type obj: L{Object}
 
-        @type chunk_size: C{int}
         @param chunk_size: Optional chunk size (in bytes).
+        @type chunk_size: C{int}
+
+        @rtype: C{object}
         """
         raise NotImplementedError(
             'download_object_as_stream not implemented for this driver')
@@ -293,17 +324,22 @@ class StorageDriver(BaseDriver):
         """
         Upload an object currently located on a disk.
 
-        @type file_path: C{str}
         @param file_path: Path to the object on disk.
+        @type file_path: C{str}
 
-        @type container: C{Container}
         @param container: Destination container.
+        @type container: L{Container}
 
-        @type object_name: C{str}
         @param object_name: Object name.
+        @type object_name: C{str}
+
+        @param verify_hash: Verify hast
+        @type verify_hash: C{bool}
 
-        @type extra: C{dict}
         @param extra: (optional) Extra attributes (driver specific).
+        @type extra: C{dict}
+
+        @rtype: C{object}
         """
         raise NotImplementedError(
             'upload_object not implemented for this driver')
@@ -320,9 +356,9 @@ class StorageDriver(BaseDriver):
         Otherwise if a provider doesn't support it, iterator will be exhausted
         so a total size for data to be uploaded can be determined.
 
-        Note: Exhausting the iterator means that the whole data must be buffered
-        in memory which might result in memory exhausting when uploading a very
-        large object.
+        Note: Exhausting the iterator means that the whole data must be
+        buffered in memory which might result in memory exhausting when
+        uploading a very large object.
 
         If a file is located on a disk you are advised to use upload_object
         function which uses fs.stat function to determine the file size and it
@@ -331,17 +367,18 @@ class StorageDriver(BaseDriver):
         @type iterator: C{object}
         @param iterator: An object which implements the iterator interface.
 
-        @type container: C{Container}
+        @type container: L{Container}
         @param container: Destination container.
 
         @type object_name: C{str}
         @param object_name: Object name.
 
         @type extra: C{dict}
-        @param extra: (optional) Extra attributes (driver specific).
+        @param extra: (optional) Extra attributes (driver specific). Note:
+            This dictionary must contain a 'content_type' key which represents
+            a content type of the stored object.
 
-        Note: This dictionary must contain a 'content_type' key which represents
-        a content type of the stored object.
+        @rtype: C{object}
         """
         raise NotImplementedError(
             'upload_object_via_stream not implemented for this driver')
@@ -350,10 +387,11 @@ class StorageDriver(BaseDriver):
         """
         Delete an object.
 
-        @type obj: C{Object}
+        @type obj: L{Object}
         @param obj: Object instance.
 
         @return: C{bool} True on success.
+        @rtype: C{bool}
         """
         raise NotImplementedError(
             'delete_object not implemented for this driver')
@@ -366,6 +404,7 @@ class StorageDriver(BaseDriver):
         @param container_name: Container name.
 
         @return: C{Container} instance on success.
+        @rtype: L{Container}
         """
         raise NotImplementedError(
             'create_container not implemented for this driver')
@@ -374,11 +413,11 @@ class StorageDriver(BaseDriver):
         """
         Delete a container.
 
-        @type container: C{Container}
+        @type container: L{Container}
         @param container: Container instance
 
-        @rtype: C{bool}
         @return: True on success, False otherwise.
+        @rtype: C{bool}
         """
         raise NotImplementedError(
             'delete_container not implemented for this driver')
@@ -392,20 +431,22 @@ class StorageDriver(BaseDriver):
         @param obj: Object instance.
 
         @type callback: C{Function}
-        @param callback: Function which is called with the passed callback_kwargs
+        @param callback: Function which is called with the passed
+            callback_kwargs
 
         @type callback_kwargs: C{dict}
-        @param callback_kwargs: Keyword arguments which are passed to the callback.
+        @param callback_kwargs: Keyword arguments which are passed to the
+             callback.
 
-        @typed response: C{Response}
+        @typed response: L{Response}
         @param response: Response instance.
 
         @type success_status_code: C{int}
         @param success_status_code: Status code which represents a successful
                                     transfer (defaults to httplib.OK)
 
-        @rtype: C{bool}
         @return: True on success, False otherwise.
+        @rtype: C{bool}
         """
         success_status_code = success_status_code or httplib.OK
 
@@ -425,27 +466,29 @@ class StorageDriver(BaseDriver):
         """
         Save object to the provided path.
 
-        @type response: C{RawResponse}
+        @type response: L{RawResponse}
         @param response: RawResponse instance.
 
-        @type obj: C{Object}
+        @type obj: L{Object}
         @param obj: Object instance.
 
-        @type destination_path: C{Str}
+        @type destination_path: C{str}
         @param destination_path: Destination directory.
 
         @type delete_on_failure: C{bool}
         @param delete_on_failure: True to delete partially downloaded object if
                                   the download fails.
+
         @type overwrite_existing: C{bool}
         @param overwrite_existing: True to overwrite a local path if it already
                                    exists.
 
         @type chunk_size: C{int}
-        @param chunk_size: Optional chunk size (defaults to L{libcloud.storage.base.CHUNK_SIZE}, 8kb)
+        @param chunk_size: Optional chunk size
+            (defaults to L{libcloud.storage.base.CHUNK_SIZE}, 8kb)
 
-        @rtype: C{bool}
         @return: True on success, False otherwise.
+        @rtype: C{bool}
         """
 
         chunk_size = chunk_size or CHUNK_SIZE
@@ -513,7 +556,7 @@ class StorageDriver(BaseDriver):
             raise OSError('File %s does not exist' % (file_path))
 
         if iterator is not None and not hasattr(iterator, 'next') and not \
-           hasattr(iterator, '__next__'):
+                hasattr(iterator, '__next__'):
             raise AttributeError('iterator object must implement next() ' +
                                  'method.')
 
@@ -536,9 +579,10 @@ class StorageDriver(BaseDriver):
                 headers['Transfer-Encoding'] = 'chunked'
                 upload_func_kwargs['chunked'] = True
             else:
-                # Chunked transfer encoding is not supported. Need to buffer all
-                # the data in memory so we can determine file size.
-                iterator = libcloud.utils.files.read_in_chunks(iterator=iterator)
+                # Chunked transfer encoding is not supported. Need to buffer
+                # all the data in memory so we can determine file size.
+                iterator = libcloud.utils.files.read_in_chunks(
+                    iterator=iterator)
                 data = libcloud.utils.files.exhaust_iterator(iterator=iterator)
 
                 file_size = len(data)
@@ -556,14 +600,15 @@ class StorageDriver(BaseDriver):
                                            headers=headers, raw=True)
 
         upload_func_kwargs['response'] = response
-        success, data_hash, bytes_transferred = upload_func(**upload_func_kwargs)
+        success, data_hash, bytes_transferred = upload_func(
+            **upload_func_kwargs)
 
         if not success:
-            raise LibcloudError(value='Object upload failed, Perhaps a timeout?',
-                                driver=self)
+            raise LibcloudError(
+                value='Object upload failed, Perhaps a timeout?', driver=self)
 
-        result_dict = { 'response': response, 'data_hash': data_hash,
-                        'bytes_transferred': bytes_transferred }
+        result_dict = {'response': response, 'data_hash': data_hash,
+                       'bytes_transferred': bytes_transferred}
         return result_dict
 
     def _upload_data(self, response, data, calculate_hash=True):
@@ -647,7 +692,7 @@ class StorageDriver(BaseDriver):
         try:
             chunk = next(generator)
         except StopIteration:
-            # Special case when StopIteration is thrown on the first iteration -
+            # Special case when StopIteration is thrown on the first iteration
             # create a 0-byte long object
             chunk = ''
             if chunked:

Modified: libcloud/branches/0.11.x/libcloud/storage/drivers/atmos.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.11.x/libcloud/storage/drivers/atmos.py?rev=1410809&r1=1410808&r2=1410809&view=diff
==============================================================================
--- libcloud/branches/0.11.x/libcloud/storage/drivers/atmos.py (original)
+++ libcloud/branches/0.11.x/libcloud/storage/drivers/atmos.py Sun Nov 18 01:22:54 2012
@@ -37,9 +37,8 @@ from libcloud.common.types import LazyLi
 
 from libcloud.storage.base import Object, Container, StorageDriver, CHUNK_SIZE
 from libcloud.storage.types import ContainerAlreadyExistsError, \
-                                   ContainerDoesNotExistError, \
-                                   ContainerIsNotEmptyError, \
-                                   ObjectDoesNotExistError
+    ContainerDoesNotExistError, ContainerIsNotEmptyError, \
+    ObjectDoesNotExistError
 
 
 def collapse(s):
@@ -125,6 +124,8 @@ class AtmosDriver(StorageDriver):
     path = None
     api_name = 'atmos'
     supports_chunked_encoding = True
+    website = 'http://atmosonline.com/'
+    name = 'atmos'
 
     DEFAULT_CDN_TTL = 60 * 60 * 24 * 7  # 1 week
 
@@ -218,7 +219,8 @@ class AtmosDriver(StorageDriver):
 
         extra = extra or {}
         object_name_cleaned = self._clean_object_name(object_name)
-        request_path = self._namespace_path(container.name) + '/' + object_name_cleaned
+        request_path = self._namespace_path(container.name) + '/' +\
+            object_name_cleaned
         content_type = extra.get('content_type', None)
 
         try:
@@ -229,13 +231,14 @@ class AtmosDriver(StorageDriver):
                 raise
             method = 'POST'
 
-        result_dict = self._upload_object(object_name=object_name,
-                                          content_type=content_type,
-                                          upload_func=upload_func,
-                                          upload_func_kwargs=upload_func_kwargs,
-                                          request_path=request_path,
-                                          request_method=method,
-                                          headers={}, file_path=file_path)
+        result_dict = self._upload_object(
+            object_name=object_name,
+            content_type=content_type,
+            upload_func=upload_func,
+            upload_func_kwargs=upload_func_kwargs,
+            request_path=request_path,
+            request_method=method,
+            headers={}, file_path=file_path)
 
         bytes_transferred = result_dict['bytes_transferred']
 
@@ -342,7 +345,7 @@ class AtmosDriver(StorageDriver):
                       meta_data, container, self)
 
     def download_object(self, obj, destination_path, overwrite_existing=False,
-                      delete_on_failure=True):
+                        delete_on_failure=True):
         path = self._namespace_path(obj.container.name + '/' + obj.name)
         response = self.connection.request(path, method='GET', raw=True)
 
@@ -370,7 +373,8 @@ class AtmosDriver(StorageDriver):
                                 success_status_code=httplib.OK)
 
     def delete_object(self, obj):
-        path = self._namespace_path(obj.container.name) + '/' + self._clean_object_name(obj.name)
+        path = self._namespace_path(obj.container.name) + '/' +\
+            self._clean_object_name(obj.name)
         try:
             self.connection.request(path, method='DELETE')
         except AtmosError:
@@ -388,6 +392,20 @@ class AtmosDriver(StorageDriver):
         return True
 
     def get_object_cdn_url(self, obj, expiry=None, use_object=False):
+        """
+        Return a object CDN URL.
+
+        @param obj: Object instance
+        @type  obj: L{Object}
+
+        @param expiry: Expiry
+        @type expiry: C{str}
+
+        @param use_object: Use object
+        @type use_object: C{bool}
+
+        @rtype: C{str}
+        """
         if use_object:
             path = '/rest/objects' + obj.meta_data['object_id']
         else:
@@ -459,6 +477,6 @@ class AtmosDriver(StorageDriver):
         objects = []
         for entry in entries:
             metadata = {'object_id': entry['id']}
-            objects.append(Object(entry['name'], 0, '', {}, metadata, container,
-                                  self))
+            objects.append(Object(entry['name'], 0, '', {}, metadata,
+                                  container, self))
         return objects, None, True

Modified: libcloud/branches/0.11.x/libcloud/storage/drivers/cloudfiles.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.11.x/libcloud/storage/drivers/cloudfiles.py?rev=1410809&r1=1410808&r2=1410809&view=diff
==============================================================================
--- libcloud/branches/0.11.x/libcloud/storage/drivers/cloudfiles.py (original)
+++ libcloud/branches/0.11.x/libcloud/storage/drivers/cloudfiles.py Sun Nov 18 01:22:54 2012
@@ -13,9 +13,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from hashlib import sha1
+import hmac
 import os
+from time import time
 
 from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import urlencode
 
 try:
     import simplejson as json
@@ -53,8 +57,7 @@ API_VERSION = 'v1.0'
 
 
 class CloudFilesResponse(Response):
-
-    valid_response_codes = [ httplib.NOT_FOUND, httplib.CONFLICT ]
+    valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT]
 
     def success(self):
         i = int(self.status)
@@ -114,11 +117,12 @@ class CloudFilesConnection(OpenStackBase
         # First, we parse out both files and cdn endpoints
         # for each auth version
         if '2.0' in self._auth_version:
-            eps = self.service_catalog.get_endpoints(service_type='object-store',
-                                                     name='cloudFiles')
+            eps = self.service_catalog.get_endpoints(
+                service_type='object-store',
+                name='cloudFiles')
             cdn_eps = self.service_catalog.get_endpoints(
-                    service_type='object-store',
-                    name='cloudFilesCDN')
+                service_type='object-store',
+                name='cloudFilesCDN')
         elif ('1.1' in self._auth_version) or ('1.0' in self._auth_version):
             eps = self.service_catalog.get_endpoints(name='cloudFiles')
             cdn_eps = self.service_catalog.get_endpoints(name='cloudFilesCDN')
@@ -176,6 +180,7 @@ class CloudFilesSwiftConnection(CloudFil
     """
     Connection class for the Cloudfiles Swift endpoint.
     """
+
     def __init__(self, *args, **kwargs):
         self.region_name = kwargs.pop('ex_region_name', None)
         super(CloudFilesSwiftConnection, self).__init__(*args, **kwargs)
@@ -183,12 +188,12 @@ class CloudFilesSwiftConnection(CloudFil
     def get_endpoint(self, *args, **kwargs):
         if '2.0' in self._auth_version:
             endpoint = self.service_catalog.get_endpoint(
-                    service_type='object-store',
-                    name='swift',
-                    region=self.region_name)
+                service_type='object-store',
+                name='swift',
+                region=self.region_name)
         elif ('1.1' in self._auth_version) or ('1.0' in self._auth_version):
-            endpoint = self.service_catalog.get_endpoint(name='swift',
-                                                   region=self.region_name)
+            endpoint = self.service_catalog.get_endpoint(
+                name='swift', region=self.region_name)
 
         if 'publicURL' in endpoint:
             return endpoint['publicURL']
@@ -204,6 +209,7 @@ class CloudFilesStorageDriver(StorageDri
     class.
     """
     name = 'CloudFiles'
+    website = 'http://www.rackspace.com/'
 
     connectionCls = CloudFilesConnection
     hash_type = 'md5'
@@ -224,12 +230,12 @@ class CloudFilesStorageDriver(StorageDri
         raise LibcloudError('Unexpected status code: %s' % (response.status))
 
     def list_container_objects(self, container):
-        value_dict = { 'container': container }
+        value_dict = {'container': container}
         return LazyList(get_more=self._get_more, value_dict=value_dict)
 
     def get_container(self, container_name):
         response = self.connection.request('/%s' % (container_name),
-                                                    method='HEAD')
+                                           method='HEAD')
 
         if response.status == httplib.NO_CONTENT:
             container = self._headers_to_container(
@@ -244,8 +250,8 @@ class CloudFilesStorageDriver(StorageDri
         container = self.get_container(container_name)
         response = self.connection.request('/%s/%s' % (container_name,
                                                        object_name),
-                                                       method='HEAD')
-        if response.status in [ httplib.OK, httplib.NO_CONTENT ]:
+                                           method='HEAD')
+        if response.status in [httplib.OK, httplib.NO_CONTENT]:
             obj = self._headers_to_object(
                 object_name, container, response.headers)
             return obj
@@ -275,6 +281,12 @@ class CloudFilesStorageDriver(StorageDri
         return '%s/%s' % (container_cdn_url, obj.name)
 
     def enable_container_cdn(self, container, ex_ttl=None):
+        """
+        @inherits: L{StorageDriver.enable_container_cdn}
+
+        @param ex_ttl: cache time to live
+        @type ex_ttl: C{int}
+        """
         container_name = container.name
         headers = {'X-CDN-Enabled': 'True'}
 
@@ -286,7 +298,7 @@ class CloudFilesStorageDriver(StorageDri
                                            headers=headers,
                                            cdn_request=True)
 
-        return response.status in [ httplib.CREATED, httplib.ACCEPTED ]
+        return response.status in [httplib.CREATED, httplib.ACCEPTED]
 
     def create_container(self, container_name):
         container_name = self._clean_container_name(container_name)
@@ -296,9 +308,9 @@ class CloudFilesStorageDriver(StorageDri
         if response.status == httplib.CREATED:
             # Accepted mean that container is not yet created but it will be
             # eventually
-            extra = { 'object_count': 0 }
+            extra = {'object_count': 0}
             container = Container(name=container_name,
-                    extra=extra, driver=self)
+                                  extra=extra, driver=self)
 
             return container
         elif response.status == httplib.ACCEPTED:
@@ -331,14 +343,14 @@ class CloudFilesStorageDriver(StorageDri
                                                        object_name),
                                            method='GET', raw=True)
 
-        return self._get_object(obj=obj, callback=self._save_object,
-                                response=response,
-                                callback_kwargs={'obj': obj,
-                                 'response': response.response,
-                                 'destination_path': destination_path,
-                                 'overwrite_existing': overwrite_existing,
-                                 'delete_on_failure': delete_on_failure},
-                                success_status_code=httplib.OK)
+        return self._get_object(
+            obj=obj, callback=self._save_object, response=response,
+            callback_kwargs={'obj': obj,
+                             'response': response.response,
+                             'destination_path': destination_path,
+                             'overwrite_existing': overwrite_existing,
+                             'delete_on_failure': delete_on_failure},
+            success_status_code=httplib.OK)
 
     def download_object_as_stream(self, obj, chunk_size=None):
         container_name = obj.container.name
@@ -361,7 +373,7 @@ class CloudFilesStorageDriver(StorageDri
         Note: This will override file with a same name if it already exists.
         """
         upload_func = self._upload_file
-        upload_func_kwargs = { 'file_path': file_path }
+        upload_func_kwargs = {'file_path': file_path}
 
         return self._put_object(container=container, object_name=object_name,
                                 upload_func=upload_func,
@@ -375,7 +387,7 @@ class CloudFilesStorageDriver(StorageDri
             iterator = iter(iterator)
 
         upload_func = self._stream_data
-        upload_func_kwargs = { 'iterator': iterator }
+        upload_func_kwargs = {'iterator': iterator}
 
         return self._put_object(container=container, object_name=object_name,
                                 upload_func=upload_func,
@@ -398,6 +410,11 @@ class CloudFilesStorageDriver(StorageDri
         raise LibcloudError('Unexpected status code: %s' % (response.status))
 
     def ex_get_meta_data(self):
+        """
+        Get meta data
+
+        @rtype: C{dict}
+        """
         response = self.connection.request('', method='HEAD')
 
         if response.status == httplib.NO_CONTENT:
@@ -407,10 +424,13 @@ class CloudFilesStorageDriver(StorageDri
                 'x-account-object-count', 'unknown')
             bytes_used = response.headers.get(
                 'x-account-bytes-used', 'unknown')
+            temp_url_key = response.headers.get(
+                'x-account-meta-temp-url-key', None)
 
-            return { 'container_count': int(container_count),
-                      'object_count': int(object_count),
-                      'bytes_used': int(bytes_used) }
+            return {'container_count': int(container_count),
+                    'object_count': int(object_count),
+                    'bytes_used': int(bytes_used),
+                    'temp_url_key': temp_url_key}
 
         raise LibcloudError('Unexpected status code: %s' % (response.status))
 
@@ -420,7 +440,7 @@ class CloudFilesStorageDriver(StorageDri
         object_size = os.path.getsize(file_path)
         if object_size < chunk_size:
             return self.upload_object(file_path, container, object_name,
-                    extra=extra, verify_hash=verify_hash)
+                                      extra=extra, verify_hash=verify_hash)
 
         iter_chunk_reader = FileChunkReader(file_path, chunk_size)
 
@@ -440,9 +460,14 @@ class CloudFilesStorageDriver(StorageDri
         """
         Enable serving a static website.
 
+        @param container: Container instance
+        @type container: L{Container}
+
         @param index_file: Name of the object which becomes an index page for
         every sub-directory in this container.
         @type index_file: C{str}
+
+        @rtype: C{bool}
         """
         container_name = container.name
         headers = {'X-Container-Meta-Web-Index': index_file}
@@ -452,15 +477,20 @@ class CloudFilesStorageDriver(StorageDri
                                            headers=headers,
                                            cdn_request=False)
 
-        return response.status in [ httplib.CREATED, httplib.ACCEPTED ]
+        return response.status in [httplib.CREATED, httplib.ACCEPTED]
 
     def ex_set_error_page(self, container, file_name='error.html'):
         """
         Set a custom error page which is displayed if file is not found and
         serving of a static website is enabled.
 
+        @param container: Container instance
+        @type container: L{Container}
+
         @param file_name: Name of the object which becomes the error page.
         @type file_name: C{str}
+
+        @rtype: C{bool}
         """
         container_name = container.name
         headers = {'X-Container-Meta-Web-Error': file_name}
@@ -470,11 +500,73 @@ class CloudFilesStorageDriver(StorageDri
                                            headers=headers,
                                            cdn_request=False)
 
-        return response.status in [ httplib.CREATED, httplib.ACCEPTED ]
+        return response.status in [httplib.CREATED, httplib.ACCEPTED]
+
+    def ex_set_account_metadata_temp_url_key(self, key):
+        """
+        Set the metadata header X-Account-Meta-Temp-URL-Key on your Cloud
+        Files account.
+
+        @param key: X-Account-Meta-Temp-URL-Key
+        @type key: C{str}
+
+        @rtype: C{bool}
+        """
+        headers = {'X-Account-Meta-Temp-URL-Key': key}
+
+        response = self.connection.request('',
+                                           method='POST',
+                                           headers=headers,
+                                           cdn_request=False)
+
+        return response.status in [httplib.OK, httplib.NO_CONTENT,
+                                   httplib.CREATED, httplib.ACCEPTED]
+
+    def ex_get_object_temp_url(self, obj, method='GET', timeout=60):
+        """
+        Create a temporary URL to allow others to retrieve or put objects
+        in your Cloud Files account for as long or as short a time as you
+        wish.  This method is specifically for allowing users to retrieve
+        or update an object.
+
+        @param obj: The object that you wish to make temporarily public
+        @type obj: L{Object}
+
+        @param method: Which method you would like to allow, 'PUT' or 'GET'
+        @type method: C{str}
+
+        @param timeout: Time (in seconds) after which you want the TempURL
+        to expire.
+        @type timeout: C{int}
+
+        @rtype: C{bool}
+        """
+        self.connection._populate_hosts_and_request_paths()
+        expires = int(time() + timeout)
+        path = '%s/%s/%s' % (self.connection.request_path,
+                             obj.container.name, obj.name)
+        try:
+            key = self.ex_get_meta_data()['temp_url_key']
+            assert key is not None
+        except Exception:
+            raise KeyError('You must first set the ' +
+                           'X-Account-Meta-Temp-URL-Key header on your ' +
+                           'Cloud Files account using ' +
+                           'ex_set_account_metadata_temp_url_key before ' +
+                           'you can use this method.')
+        hmac_body = '%s\n%s\n%s' % (method, expires, path)
+        sig = hmac.new(b(key), b(hmac_body), sha1).hexdigest()
+        params = urlencode({'temp_url_sig': sig,
+                            'temp_url_expires': expires})
+
+        temp_url = 'https://%s/%s/%s?%s' %\
+                   (self.connection.host + self.connection.request_path,
+                    obj.container.name, obj.name, params)
+
+        return temp_url
 
     def _upload_object_part(self, container, object_name, part_number,
                             iterator, verify_hash=True):
-
         upload_func = self._stream_data
         upload_func_kwargs = {'iterator': iterator}
         part_name = object_name + '/%08d' % part_number
@@ -497,8 +589,9 @@ class CloudFilesStorageDriver(StorageDri
         request_path = '/%s/%s' % (container_name_cleaned, object_name_cleaned)
 
         headers = {'X-Auth-Token': self.connection.auth_token,
-                   'X-Object-Manifest': '%s/%s/' % \
-                       (container_name_cleaned, object_name_cleaned)}
+                   'X-Object-Manifest': '%s/%s/' %
+                                        (container_name_cleaned,
+                                         object_name_cleaned)}
 
         data = ''
         response = self.connection.request(request_path,
@@ -516,8 +609,8 @@ class CloudFilesStorageDriver(StorageDri
             if object_hash != data_hash:
                 raise ObjectHashMismatchError(
                     value=('MD5 hash checksum does not match (expected=%s, ' +
-                           'actual=%s)') % \
-                           (data_hash, object_hash),
+                           'actual=%s)') %
+                          (data_hash, object_hash),
                     object_name=object_name, driver=self)
 
         obj = Object(name=object_name, size=0, hash=object_hash, extra=None,
@@ -533,14 +626,14 @@ class CloudFilesStorageDriver(StorageDri
             params['marker'] = last_key
 
         response = self.connection.request('/%s' % (container.name),
-                                          params=params)
+                                           params=params)
 
         if response.status == httplib.NO_CONTENT:
             # Empty or inexistent container
             return [], None, True
         elif response.status == httplib.OK:
             objects = self._to_object_list(json.loads(response.body),
-                    container)
+                                           container)
 
             # TODO: Is this really needed?
             if len(objects) == 0:
@@ -566,14 +659,11 @@ class CloudFilesStorageDriver(StorageDri
                 headers[key] = value
 
         request_path = '/%s/%s' % (container_name_cleaned, object_name_cleaned)
-        result_dict = self._upload_object(object_name=object_name,
-                                         content_type=content_type,
-                                         upload_func=upload_func,
-                                         upload_func_kwargs=upload_func_kwargs,
-                                         request_path=request_path,
-                                         request_method='PUT',
-                                         headers=headers, file_path=file_path,
-                                         iterator=iterator)
+        result_dict = self._upload_object(
+            object_name=object_name, content_type=content_type,
+            upload_func=upload_func, upload_func_kwargs=upload_func_kwargs,
+            request_path=request_path, request_method='PUT',
+            headers=headers, file_path=file_path, iterator=iterator)
 
         response = result_dict['response'].response
         bytes_transferred = result_dict['bytes_transferred']
@@ -616,9 +706,9 @@ class CloudFilesStorageDriver(StorageDri
                                             container_name=name, driver=self)
 
         if len(name) > 256:
-            raise InvalidContainerNameError(value='Container name cannot be'
-                                                   ' longer than 256 bytes',
-                                            container_name=name, driver=self)
+            raise InvalidContainerNameError(
+                value='Container name cannot be longer than 256 bytes',
+                container_name=name, driver=self)
 
         return name
 
@@ -631,8 +721,8 @@ class CloudFilesStorageDriver(StorageDri
         containers = []
 
         for container in response:
-            extra = { 'object_count': int(container['count']),
-                      'size': int(container['bytes'])}
+            extra = {'object_count': int(container['count']),
+                     'size': int(container['bytes'])}
             containers.append(Container(name=container['name'], extra=extra,
                                         driver=self))
 
@@ -645,8 +735,8 @@ class CloudFilesStorageDriver(StorageDri
             name = obj['name']
             size = int(obj['bytes'])
             hash = obj['hash']
-            extra = { 'content_type': obj['content_type'],
-                      'last_modified': obj['last_modified'] }
+            extra = {'content_type': obj['content_type'],
+                     'last_modified': obj['last_modified']}
             objects.append(Object(
                 name=name, size=size, hash=hash, extra=extra,
                 meta_data=None, container=container, driver=self))
@@ -657,8 +747,8 @@ class CloudFilesStorageDriver(StorageDri
         size = int(headers.get('x-container-bytes-used', 0))
         object_count = int(headers.get('x-container-object-count', 0))
 
-        extra = { 'object_count': object_count,
-                  'size': size }
+        extra = {'object_count': object_count,
+                 'size': size}
         container = Container(name=name, extra=extra, driver=self)
         return container
 
@@ -707,8 +797,8 @@ class CloudFilesSwiftStorageDriver(Cloud
         super(CloudFilesSwiftStorageDriver, self).__init__(*args, **kwargs)
 
     def openstack_connection_kwargs(self):
-        rv = super(CloudFilesSwiftStorageDriver, self). \
-                                                  openstack_connection_kwargs()
+        rv = super(CloudFilesSwiftStorageDriver,
+                   self).openstack_connection_kwargs()
         rv['ex_region_name'] = self._ex_region_name
         return rv
 
@@ -752,6 +842,7 @@ class FileChunkReader(object):
     def __next__(self):
         return self.next()
 
+
 class ChunkStreamReader(object):
     def __init__(self, file_path, start_block, end_block, chunk_size):
         self.fd = open(file_path, 'rb')
@@ -771,11 +862,10 @@ class ChunkStreamReader(object):
             raise StopIteration
 
         block_size = self.chunk_size
-        if self.bytes_read + block_size > \
-            self.end_block - self.start_block:
-                block_size = self.end_block - self.start_block - \
-                             self.bytes_read
-                self.stop_iteration = True
+        if self.bytes_read + block_size >\
+                self.end_block - self.start_block:
+            block_size = self.end_block - self.start_block - self.bytes_read
+            self.stop_iteration = True
 
         block = self.fd.read(block_size)
         self.bytes_read += block_size