You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by pq...@apache.org on 2011/09/18 01:35:46 UTC
svn commit: r1172148 - in /libcloud/trunk: libcloud/ libcloud/common/
libcloud/compute/ libcloud/compute/drivers/ libcloud/loadbalancer/drivers/
libcloud/storage/drivers/ test/ test/compute/ test/loadbalancer/
test/openstack/ test/openstack/fixtures/ t...
Author: pquerna
Date: Sat Sep 17 23:35:45 2011
New Revision: 1172148
URL: http://svn.apache.org/viewvc?rev=1172148&view=rev
Log:
Refactoring of how OpenStack based drivers authenticate and find their base URLs. This also changed how other drivers did 'secure' port selection, and make Connection.port the actual port we are connecting on, and Connection.secure to just be an indiciator if we should use SSL or not, rather than changing the port.
Added:
libcloud/trunk/test/openstack/
libcloud/trunk/test/openstack/fixtures/
libcloud/trunk/test/openstack/fixtures/_v1_1__auth.json
libcloud/trunk/test/openstack/fixtures/_v1_1__auth_mssing_token.json
libcloud/trunk/test/openstack/fixtures/_v1_1__auth_unauthorized.json
Modified:
libcloud/trunk/libcloud/__init__.py
libcloud/trunk/libcloud/common/base.py
libcloud/trunk/libcloud/common/openstack.py
libcloud/trunk/libcloud/common/rackspace.py
libcloud/trunk/libcloud/compute/base.py
libcloud/trunk/libcloud/compute/drivers/openstack.py
libcloud/trunk/libcloud/compute/drivers/rackspace.py
libcloud/trunk/libcloud/compute/drivers/rimuhosting.py
libcloud/trunk/libcloud/compute/drivers/vcloud.py
libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py
libcloud/trunk/libcloud/storage/drivers/cloudfiles.py
libcloud/trunk/test/compute/test_deployment.py
libcloud/trunk/test/compute/test_openstack.py
libcloud/trunk/test/file_fixtures.py
libcloud/trunk/test/loadbalancer/test_rackspace.py
libcloud/trunk/test/storage/test_cloudfiles.py
Modified: libcloud/trunk/libcloud/__init__.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/__init__.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/__init__.py (original)
+++ libcloud/trunk/libcloud/__init__.py Sat Sep 17 23:35:45 2011
@@ -32,12 +32,12 @@ def enable_debug(fo):
@param fo: Where to append debugging information
@type fo: File like object, only write operations are used.
"""
- from libcloud.base import (ConnectionKey,
+ from libcloud.common.base import (Connection,
LoggingHTTPConnection,
LoggingHTTPSConnection)
LoggingHTTPSConnection.log = fo
LoggingHTTPConnection.log = fo
- ConnectionKey.conn_classes = (LoggingHTTPConnection,
+ Connection.conn_classes = (LoggingHTTPConnection,
LoggingHTTPSConnection)
Modified: libcloud/trunk/libcloud/common/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/base.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/base.py (original)
+++ libcloud/trunk/libcloud/common/base.py Sat Sep 17 23:35:45 2011
@@ -19,8 +19,10 @@ import StringIO
import ssl
from pipes import quote as pquote
+import urlparse
import libcloud
+from libcloud.common.types import LibcloudError
from libcloud.httplib_ssl import LibcloudHTTPSConnection
from httplib import HTTPConnection as LibcloudHTTPConnection
@@ -222,7 +224,7 @@ class LoggingHTTPConnection(LoggingConne
return LibcloudHTTPConnection.request(self, method, url,
body, headers)
-class ConnectionKey(object):
+class Connection(object):
"""
A Base Connection class to derive from.
"""
@@ -233,26 +235,57 @@ class ConnectionKey(object):
rawResponseCls = RawResponse
connection = None
host = '127.0.0.1'
- port = (80, 443)
+ port = 443
secure = 1
driver = None
action = None
- def __init__(self, key, secure=True, host=None, force_port=None):
- """
- Initialize `user_id` and `key`; set `secure` to an C{int} based on
- passed value.
- """
- self.key = key
+ def __init__(self, secure=True, host=None, port=None, url=None):
self.secure = secure and 1 or 0
self.ua = []
+
+ self.request_path = ''
+
if host:
self.host = host
- if force_port:
- self.port = (force_port, force_port)
+ if port != None:
+ self.port = port
+ else:
+ if self.secure == 1:
+ self.port = 443
+ else:
+ self.port = 80
+
+ if url:
+ (self.host, self.port, self.secure, self.request_path) = self._tuple_from_url(url)
+
+ def _tuple_from_url(self, url):
+ secure = 1
+ port = None
+ scheme, netloc, request_path, param, query, fragment = urlparse.urlparse(url)
+
+ if scheme not in ['http', 'https']:
+ raise LibcloudError('Invalid scheme: %s in url %s' % (scheme, url))
- def connect(self, host=None, port=None):
+ if scheme == "http":
+ secure = 0
+
+ if ":" in netloc:
+ netloc, port = netloc.rsplit(":")
+ port = port
+
+ if not port:
+ if scheme == "http":
+ port = 80
+ else:
+ port = 443
+
+ host = netloc
+
+ return (host, port, secure, request_path)
+
+ def connect(self, host=None, port=None, base_url = None):
"""
Establish a connection with the API server.
@@ -264,17 +297,21 @@ class ConnectionKey(object):
@returns: A connection
"""
- host = host or self.host
-
- # port might be included in service url, so pick it if it's present
- if ":" in host:
- host, port = host.split(":")
+ # prefer the attribute base_url if its set or sent
+ connection = None
+ secure = self.secure
+
+ if getattr(self, 'base_url', None) and base_url == None:
+ (host, port, secure, request_path) = self._tuple_from_url(self.base_url)
+ elif base_url != None:
+ (host, port, secure, request_path) = self._tuple_from_url(base_url)
else:
- port = port or self.port[self.secure]
+ host = host or self.host
+ port = port or self.port
kwargs = {'host': host, 'port': int(port)}
- connection = self.conn_classes[self.secure](**kwargs)
+ connection = self.conn_classes[secure](**kwargs)
# You can uncoment this line, if you setup a reverse proxy server
# which proxies to your endpoint, and lets you easily capture
# connections in cleartext when you setup the proxy to do SSL
@@ -307,8 +344,7 @@ class ConnectionKey(object):
data='',
headers=None,
method='GET',
- raw=False,
- host=None):
+ raw=False):
"""
Request a given `action`.
@@ -337,10 +373,6 @@ class ConnectionKey(object):
and use the rawResponseCls class. This is used with
storage API when uploading a file.
- @type host: C{str}
- @param host: To which host to send the request. If not specified,
- self.host is used.
-
@return: An instance of type I{responseCls}
"""
if params is None:
@@ -348,6 +380,7 @@ class ConnectionKey(object):
if headers is None:
headers = {}
+ action = self.morph_action_hook(action)
self.action = action
self.method = method
# Extend default parameters
@@ -356,8 +389,7 @@ class ConnectionKey(object):
headers = self.add_default_headers(headers)
# We always send a user-agent header
headers.update({'User-Agent': self._user_agent()})
- host = host or self.host
- headers.update({'Host': host})
+ headers.update({'Host': self.host})
# Encode data if necessary
if data != '' and data != None:
data = self.encode_data(data)
@@ -374,7 +406,7 @@ class ConnectionKey(object):
# Removed terrible hack...this a less-bad hack that doesn't execute a
# request twice, but it's still a hack.
- self.connect(host=host)
+ self.connect()
try:
# @TODO: Should we just pass File object as body to request method
# instead of dealing with splitting and sending the file ourselves?
@@ -399,6 +431,9 @@ class ConnectionKey(object):
response.connection = self
return response
+ def morph_action_hook(self, action):
+ return self.request_path + action
+
def add_default_params(self, params):
"""
Adds default parameters (such as API key, version, etc.)
@@ -438,6 +473,18 @@ class ConnectionKey(object):
Override in a provider's subclass.
"""
return data
+
+class ConnectionKey(Connection):
+ """
+ A Base Connection class to derive from, which includes a
+ """
+ def __init__(self, key, secure=True, host=None, port=None, url=None):
+ """
+ Initialize `user_id` and `key`; set `secure` to an C{int} based on
+ passed value.
+ """
+ super(ConnectionKey, self).__init__(secure=secure, host=host, port=port, url=url)
+ self.key = key
class ConnectionUserAndKey(ConnectionKey):
"""
@@ -446,6 +493,7 @@ class ConnectionUserAndKey(ConnectionKey
user_id = None
- def __init__(self, user_id, key, secure=True, host=None, port=None):
- super(ConnectionUserAndKey, self).__init__(key, secure, host, port)
+ def __init__(self, user_id, key, secure=True, host=None, port=None, url=None):
+ super(ConnectionUserAndKey, self).__init__(key, secure=secure,
+ host=host, port=port, url=url)
self.user_id = user_id
Modified: libcloud/trunk/libcloud/common/openstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/openstack.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/openstack.py (original)
+++ libcloud/trunk/libcloud/common/openstack.py Sat Sep 17 23:35:45 2011
@@ -18,65 +18,163 @@ Common utilities for OpenStack
"""
import httplib
from urllib2 import urlparse
-from libcloud.common.base import ConnectionUserAndKey
-from libcloud.compute.types import InvalidCredsError, MalformedResponseError
+from libcloud.common.base import ConnectionUserAndKey, Response
+from libcloud.compute.types import LibcloudError, InvalidCredsError, MalformedResponseError
+
+try:
+ import simplejson as json
+except ImportError:
+ import json
AUTH_API_VERSION = 'v1.0'
__all__ = [
"OpenStackBaseConnection",
+ "OpenStackAuthConnection",
]
+
+# @TODO: Refactor for re-use by other openstack drivers
+class OpenStackAuthResponse(Response):
+ def success(self):
+ return True
+
+ def parse_body(self):
+ if not self.body:
+ return None
+
+ if 'content-type' in self.headers:
+ key = 'content-type'
+ elif 'Content-Type' in self.headers:
+ key = 'Content-Type'
+ else:
+ raise LibcloudError('Missing content-type header', driver=OpenStackAuthConnection)
+
+ content_type = self.headers[key]
+ if content_type.find(';') != -1:
+ content_type = content_type.split(';')[0]
+
+ if content_type == 'application/json':
+ try:
+ data = json.loads(self.body)
+ except:
+ raise MalformedResponseError('Failed to parse JSON',
+ body=self.body,
+ driver=OpenStackAuthConnection)
+ elif content_type == 'text/plain':
+ data = self.body
+ else:
+ data = self.body
+
+ return data
+
+class OpenStackAuthConnection(ConnectionUserAndKey):
+
+ responseCls = OpenStackAuthResponse
+ name = 'OpenStack Auth'
+
+ def __init__(self, parent_conn, auth_url, user_id, key):
+ self.parent_conn = parent_conn
+ # enable tests to use the same mock connection classes.
+ self.conn_classes = parent_conn.conn_classes
+
+ super(OpenStackAuthConnection, self).__init__(
+ user_id, key, url=auth_url)
+
+ self.auth_url = auth_url
+ self.urls = {}
+ self.driver = self.parent_conn.driver
+
+ def add_default_headers(self, headers):
+ headers['Accept'] = 'application/json'
+ headers['Content-Type'] = 'application/json; charset=UTF-8'
+ return headers
+
+ def authenticate(self):
+ reqbody = json.dumps({'credentials': {'username': self.user_id, 'key': self.key}})
+ resp = self.request("/auth",
+ data=reqbody,
+ headers={
+ 'X-Auth-User': self.user_id,
+ 'X-Auth-Key': self.key,
+ },
+ method='POST')
+
+ if resp.status == httplib.UNAUTHORIZED:
+ # HTTP UNAUTHORIZED (401): auth failed
+ raise InvalidCredsError()
+ elif resp.status != httplib.OK:
+ raise MalformedResponseError('Malformed response',
+ body='code: %s body:%s' % (resp.status, resp.body),
+ driver=self.driver)
+ else:
+ try:
+ body = json.loads(resp.body)
+ except Exception, e:
+ raise MalformedResponseError('Failed to parse JSON', e)
+ try:
+ self.auth_token = body['auth']['token']['id']
+ self.urls = body['auth']['serviceCatalog']
+ except KeyError, e:
+ raise MalformedResponseError('Auth JSON response is missing required elements', e)
+
class OpenStackBaseConnection(ConnectionUserAndKey):
- auth_host = None
+ auth_url = None
- def __init__(self, user_id, key, secure, host=None, port=None):
+ def __init__(self, user_id, key, secure=True,
+ host=None, port=None, ex_force_base_url=None):
+ self.server_url = None
self.cdn_management_url = None
self.storage_url = None
+ self.lb_url = None
self.auth_token = None
- if host is not None:
- self.auth_host = host
- if port is not None:
- self.port = (port, port)
-
+ self._force_base_url = ex_force_base_url
super(OpenStackBaseConnection, self).__init__(
- user_id, key, secure=secure)
+ user_id, key)
def add_default_headers(self, headers):
headers['X-Auth-Token'] = self.auth_token
headers['Accept'] = self.accept_format
return headers
- @property
- def request_path(self):
- return self._get_request_path(url_key=self._url_key)
-
- @property
- def host(self):
- # Default to server_host
- return self._get_host(url_key=self._url_key)
-
- def _get_request_path(self, url_key):
- value_key = '__request_path_%s' % (url_key)
- value = getattr(self, value_key, None)
+ def morph_action(self, action):
+ key = self._url_key
+ value = getattr(self, key, None)
if not value:
self._populate_hosts_and_request_paths()
- value = getattr(self, value_key, None)
- return value
+ request_path = getattr(self, '__request_path_%s' % (key), '')
+ action = request_path + action
+ return action
- def _get_host(self, url_key):
- value_key = '__%s' % (url_key)
- value = getattr(self, value_key, None)
+ @property
+ def base_url(self):
+ return self._get_base_url(url_key=self._url_key)
+ def _get_base_url(self, url_key):
+ value = getattr(self, url_key, None)
if not value:
self._populate_hosts_and_request_paths()
- value = getattr(self, value_key, None)
-
+ value = getattr(self, url_key, None)
+ if self._force_base_url != None:
+ value = self._force_base_url
return value
+ def _get_default_region(self, arr):
+ if len(arr):
+ for i in arr:
+ if i.get('v1Default', False):
+ return i['publicURL']
+ # uber lame
+ return arr[0]
+ return None
+
+ def request(self, **kwargs):
+ self._populate_hosts_and_request_paths()
+ return super(OpenStackBaseConnection, self).request(**kwargs)
+
def _populate_hosts_and_request_paths(self):
"""
OpenStack uses a separate host for API calls which is only provided
@@ -84,50 +182,36 @@ class OpenStackBaseConnection(Connection
request yet, do it here. Otherwise, just return the management host.
"""
if not self.auth_token:
- # Initial connection used for authentication
- conn = self.conn_classes[self.secure](
- self.auth_host, self.port[self.secure])
- conn.request(
- method='GET',
- url='/%s' % (AUTH_API_VERSION),
- headers={
- 'X-Auth-User': self.user_id,
- 'X-Auth-Key': self.key
- }
- )
-
- resp = conn.getresponse()
-
- if resp.status == httplib.NO_CONTENT:
- # HTTP NO CONTENT (204): auth successful
- headers = dict(resp.getheaders())
-
- try:
- self.server_url = headers['x-server-management-url']
- self.storage_url = headers['x-storage-url']
- self.cdn_management_url = headers['x-cdn-management-url']
- self.lb_url = self.server_url.replace("servers", "ord.loadbalancers")
- self.auth_token = headers['x-auth-token']
- except KeyError, e:
- # Returned 204 but has missing information in the header, something is wrong
- raise MalformedResponseError('Malformed response',
- body='Missing header: %s' % (str(e)),
- driver=self.driver)
- elif resp.status == httplib.UNAUTHORIZED:
- # HTTP UNAUTHORIZED (401): auth failed
- raise InvalidCredsError()
- else:
- # Any response code != 401 or 204, something is wrong
- raise MalformedResponseError('Malformed response',
- body='code: %s body:%s' % (resp.status, ''.join(resp.body.readlines())),
- driver=self.driver)
+ if self.auth_url == None:
+ raise LibcloudError('OpenStack instance must have auth_url set')
+
+ osa = OpenStackAuthConnection(self, self.auth_url, self.user_id, self.key)
+
+ # may throw InvalidCreds, etc
+ osa.authenticate()
+
+ self.auth_token = osa.auth_token
+
+ # TODO: Multi-region support
+ self.server_url = self._get_default_region(osa.urls.get('cloudServers', []))
+ self.cdn_management_url = self._get_default_region(osa.urls.get('cloudFilesCDN', []))
+ self.storage_url = self._get_default_region(osa.urls.get('cloudFiles', []))
+ # TODO: this is even more broken, the service catalog does NOT show load
+ # balanacers :( You must hard code in the Rackspace Load balancer URLs...
+ self.lb_url = self.server_url.replace("servers", "ord.loadbalancers")
for key in ['server_url', 'storage_url', 'cdn_management_url',
'lb_url']:
+ base_url = None
+ if self._force_base_url != None:
+ base_url = self._force_base_url
+ else:
+ base_url = getattr(self, key)
+
scheme, server, request_path, param, query, fragment = (
- urlparse.urlparse(getattr(self, key)))
+ urlparse.urlparse(base_url))
# Set host to where we want to make further requests to
setattr(self, '__%s' % (key), server)
setattr(self, '__request_path_%s' % (key), request_path)
- conn.close()
+ (self.host, self.port, self.secure, self.request_path) = self._tuple_from_url(self.base_url)
Modified: libcloud/trunk/libcloud/common/rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/rackspace.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/rackspace.py (original)
+++ libcloud/trunk/libcloud/common/rackspace.py Sat Sep 17 23:35:45 2011
@@ -17,10 +17,10 @@
Common settings for Rackspace Cloud Servers and Cloud Files
"""
-AUTH_HOST_US = 'auth.api.rackspacecloud.com'
-AUTH_HOST_UK = 'lon.auth.api.rackspacecloud.com'
+AUTH_URL_US = 'https://auth.api.rackspacecloud.com/v1.1/'
+AUTH_URL_UK = 'https://lon.auth.api.rackspacecloud.com/v1.1/'
__all__ = [
- "AUTH_HOST_US",
- "AUTH_HOST_UK",
+ "AUTH_URL_US",
+ "AUTH_URL_UK",
]
Modified: libcloud/trunk/libcloud/compute/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/base.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/base.py (original)
+++ libcloud/trunk/libcloud/compute/base.py Sat Sep 17 23:35:45 2011
@@ -382,11 +382,14 @@ class NodeDriver(object):
if port != None:
args.append(port)
- self.connection = self.connectionCls(*args)
+ self.connection = self.connectionCls(*args, **self._ex_connection_class_kwargs())
self.connection.driver = self
self.connection.connect()
+ def _ex_connection_class_kwargs(self):
+ return {}
+
def create_node(self, **kwargs):
"""Create a new node instance.
Modified: libcloud/trunk/libcloud/compute/drivers/openstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/openstack.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/openstack.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/openstack.py Sat Sep 17 23:35:45 2011
@@ -89,9 +89,9 @@ class OpenStackConnection(OpenStackBaseC
responseCls = OpenStackResponse
_url_key = "server_url"
- def __init__(self, user_id, key, secure, host=None, port=None):
+ def __init__(self, user_id, key, secure=True, host=None, port=None, ex_force_base_url=None):
super(OpenStackConnection, self).__init__(
- user_id, key, secure=secure, host=host, port=port)
+ user_id, key, host=host, port=port, ex_force_base_url=ex_force_base_url)
self.api_version = 'v1.0'
self.accept_format = 'application/xml'
@@ -101,9 +101,7 @@ class OpenStackConnection(OpenStackBaseC
headers = {}
if not params:
params = {}
- # Due to first-run authentication request, we may not have a path
- if self.server_url:
- action = self.server_url + action
+
if method in ("POST", "PUT"):
headers = {'Content-Type': 'application/xml; charset=UTF-8'}
if method == "GET":
@@ -149,6 +147,16 @@ class OpenStackNodeDriver(NodeDriver):
'DELETE_IP': NodeState.PENDING,
'UNKNOWN': NodeState.UNKNOWN}
+ def __init__(self, *args, **kwargs):
+ self._ex_force_base_url = kwargs.pop('ex_force_base_url', None)
+ super(OpenStackNodeDriver, self).__init__(*args, **kwargs)
+
+ def _ex_connection_class_kwargs(self):
+ if self._ex_force_base_url:
+ return {'ex_force_base_url': self._ex_force_base_url}
+ return {}
+
+
def list_nodes(self):
return self._to_nodes(self.connection.request('/servers/detail')
.object)
Modified: libcloud/trunk/libcloud/compute/drivers/rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/rackspace.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/rackspace.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/rackspace.py Sat Sep 17 23:35:45 2011
@@ -20,7 +20,7 @@ from libcloud.compute.base import NodeLo
from libcloud.compute.drivers.openstack import OpenStackConnection, OpenStackNodeDriver, OpenStackResponse
from libcloud.common.rackspace import (
- AUTH_HOST_US, AUTH_HOST_UK)
+ AUTH_URL_US, AUTH_URL_UK)
class RackspaceConnection(OpenStackConnection):
@@ -29,7 +29,7 @@ class RackspaceConnection(OpenStackConne
"""
responseCls = OpenStackResponse
- auth_host = AUTH_HOST_US
+ auth_url = AUTH_URL_US
class RackspaceNodeDriver(OpenStackNodeDriver):
@@ -51,7 +51,7 @@ class RackspaceUKConnection(RackspaceCon
"""
Connection class for the Rackspace UK driver
"""
- auth_host = AUTH_HOST_UK
+ auth_url = AUTH_URL_UK
class RackspaceUKNodeDriver(RackspaceNodeDriver):
Modified: libcloud/trunk/libcloud/compute/drivers/rimuhosting.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/rimuhosting.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/rimuhosting.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/rimuhosting.py Sat Sep 17 23:35:45 2011
@@ -28,8 +28,6 @@ from libcloud.compute.base import NodeIm
API_CONTEXT = '/r'
API_HOST = 'rimuhosting.com'
-API_PORT = (80,443)
-API_SECURE = True
class RimuHostingException(Exception):
"""
@@ -78,7 +76,7 @@ class RimuHostingConnection(ConnectionKe
api_context = API_CONTEXT
host = API_HOST
- port = API_PORT
+ port = 443
responseCls = RimuHostingResponse
def __init__(self, key, secure=True):
@@ -113,8 +111,8 @@ class RimuHostingNodeDriver(NodeDriver):
name = 'RimuHosting'
connectionCls = RimuHostingConnection
- def __init__(self, key, host=API_HOST, port=API_PORT,
- api_context=API_CONTEXT, secure=API_SECURE):
+ def __init__(self, key, host=API_HOST, port=443,
+ api_context=API_CONTEXT, secure=True):
# Pass in some extra vars so that
self.key = key
self.secure = secure
Modified: libcloud/trunk/libcloud/compute/drivers/vcloud.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/vcloud.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/vcloud.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/vcloud.py Sat Sep 17 23:35:45 2011
@@ -244,7 +244,7 @@ class VCloudConnection(ConnectionUserAnd
def _get_auth_token(self):
if not self.token:
conn = self.conn_classes[self.secure](self.host,
- self.port[self.secure])
+ self.port)
conn.request(method='POST', url='/api/v0.8/login',
headers=self._get_auth_headers())
Modified: libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py Sat Sep 17 23:35:45 2011
@@ -27,7 +27,7 @@ from libcloud.loadbalancer.base import D
from libcloud.loadbalancer.types import State
from libcloud.common.openstack import OpenStackBaseConnection
from libcloud.common.rackspace import (
- AUTH_HOST_US, AUTH_HOST_UK)
+ AUTH_URL_US, AUTH_URL_UK)
class RackspaceResponse(Response):
@@ -43,7 +43,7 @@ class RackspaceResponse(Response):
class RackspaceConnection(OpenStackBaseConnection):
responseCls = RackspaceResponse
- auth_host = AUTH_HOST_US
+ auth_url = AUTH_URL_US
_url_key = "lb_url"
def __init__(self, user_id, key, secure=True):
@@ -56,8 +56,7 @@ class RackspaceConnection(OpenStackBaseC
headers = {}
if not params:
params = {}
- if self.lb_url:
- action = self.lb_url + action
+
if method in ('POST', 'PUT'):
headers['Content-Type'] = 'application/json'
if method == 'GET':
@@ -68,7 +67,7 @@ class RackspaceConnection(OpenStackBaseC
class RackspaceUKConnection(RackspaceConnection):
- auth_host = AUTH_HOST_UK
+ auth_url = AUTH_URL_UK
class RackspaceLBDriver(Driver):
Modified: libcloud/trunk/libcloud/storage/drivers/cloudfiles.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/drivers/cloudfiles.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/drivers/cloudfiles.py (original)
+++ libcloud/trunk/libcloud/storage/drivers/cloudfiles.py Sat Sep 17 23:35:45 2011
@@ -37,7 +37,7 @@ from libcloud.common.types import LazyLi
from libcloud.common.openstack import OpenStackBaseConnection
from libcloud.common.rackspace import (
- AUTH_HOST_US, AUTH_HOST_UK)
+ AUTH_URL_US, AUTH_URL_UK)
CDN_HOST = 'cdn.clouddrive.com'
API_VERSION = 'v1.0'
@@ -88,9 +88,9 @@ class CloudFilesConnection(OpenStackBase
Base connection class for the Cloudfiles driver.
"""
+ auth_url = AUTH_URL_US
responseCls = CloudFilesResponse
rawResponseCls = CloudFilesRawResponse
- auth_host = None
_url_key = "storage_url"
def __init__(self, user_id, key, secure=True):
@@ -110,10 +110,8 @@ class CloudFilesConnection(OpenStackBase
else:
host = None
- # Due to first-run authentication request, we may not have a path
- if self.request_path:
- action = self.request_path + action
- params['format'] = 'json'
+ params['format'] = 'json'
+
if method in [ 'POST', 'PUT' ]:
headers.update({'Content-Type': 'application/json; charset=UTF-8'})
@@ -121,8 +119,7 @@ class CloudFilesConnection(OpenStackBase
action=action,
params=params, data=data,
method=method, headers=headers,
- raw=raw, host=host
- )
+ raw=raw)
class CloudFilesUSConnection(CloudFilesConnection):
@@ -130,7 +127,7 @@ class CloudFilesUSConnection(CloudFilesC
Connection class for the Cloudfiles US endpoint.
"""
- auth_host = AUTH_HOST_US
+ auth_url = AUTH_URL_US
class CloudFilesUKConnection(CloudFilesConnection):
@@ -138,7 +135,7 @@ class CloudFilesUKConnection(CloudFilesC
Connection class for the Cloudfiles UK endpoint.
"""
- auth_host = AUTH_HOST_UK
+ auth_url = AUTH_URL_UK
class CloudFilesStorageDriver(StorageDriver):
@@ -149,6 +146,7 @@ class CloudFilesStorageDriver(StorageDri
class.
"""
name = 'CloudFiles'
+
connectionCls = CloudFilesConnection
hash_type = 'md5'
Modified: libcloud/trunk/test/compute/test_deployment.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/test_deployment.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/test/compute/test_deployment.py (original)
+++ libcloud/trunk/test/compute/test_deployment.py Sat Sep 17 23:35:45 2011
@@ -27,7 +27,7 @@ from libcloud.compute.ssh import BaseSSH
from libcloud.compute.drivers.rackspace import RackspaceNodeDriver as Rackspace
from test import MockHttp, XML_HEADERS
-from test.file_fixtures import ComputeFileFixtures
+from test.file_fixtures import ComputeFileFixtures, OpenStackFixtures
from mock import Mock, patch
from test.secrets import RACKSPACE_PARAMS
@@ -321,6 +321,11 @@ class DeploymentTests(unittest.TestCase)
class RackspaceMockHttp(MockHttp):
fixtures = ComputeFileFixtures('openstack')
+ auth_fixtures = OpenStackFixtures()
+
+ def _v1_1__auth(self, method, url, body, headers):
+ body = self.auth_fixtures.load('_v1_1__auth.json')
+ return (httplib.OK, body, {'content-type': 'application/json; charset=UTF-8'}, httplib.responses[httplib.OK])
# fake auth token response
def _v1_0(self, method, url, body, headers):
Modified: libcloud/trunk/test/compute/test_openstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/test_openstack.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/test/compute/test_openstack.py (original)
+++ libcloud/trunk/test/compute/test_openstack.py Sat Sep 17 23:35:45 2011
@@ -22,7 +22,7 @@ from libcloud.compute.base import Node,
from libcloud.pricing import set_pricing, clear_pricing_data
from test import MockResponse, MockHttpTestCase, XML_HEADERS
-from test.file_fixtures import ComputeFileFixtures
+from test.file_fixtures import ComputeFileFixtures, OpenStackFixtures
from test.compute import TestCaseMixin
from test.secrets import OPENSTACK_PARAMS
@@ -66,6 +66,7 @@ class OpenStackTests(unittest.TestCase,
def setUp(self):
self.driver_type.connectionCls.conn_classes = (OpenStackMockHttp, OpenStackMockHttp)
+ self.driver_type.connectionCls.auth_url = "https://auth.api.example.com/v1.1/"
OpenStackMockHttp.type = None
self.driver = self.create_driver()
clear_pricing_data()
@@ -292,6 +293,8 @@ class OpenStackTests(unittest.TestCase,
class OpenStackMockHttp(MockHttpTestCase):
fixtures = ComputeFileFixtures('openstack')
+ auth_fixtures = OpenStackFixtures()
+ json_content_headers = {'content-type': 'application/json; charset=UTF-8'}
# fake auth token response
def _v1_0(self, method, url, body, headers):
@@ -408,6 +411,22 @@ class OpenStackMockHttp(MockHttpTestCase
headers.update(XML_HEADERS)
return (httplib.OK, body, headers, httplib.responses[httplib.OK])
+ def _v1_1__auth(self, method, url, body, headers):
+ body = self.auth_fixtures.load('_v1_1__auth.json')
+ return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+
+ def _v1_1__auth_UNAUTHORIZED(self, method, url, body, headers):
+ body = self.auth_fixtures.load('_v1_1__auth_unauthorized.json')
+ return (httplib.UNAUTHORIZED, body, self.json_content_headers, httplib.responses[httplib.UNAUTHORIZED])
+
+ def _v1_1__auth_UNAUTHORIZED_MISSING_KEY(self, method, url, body, headers):
+ body = self.auth_fixtures.load('_v1_1__auth_mssing_token.json')
+ return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+
+ def _v1_1__auth_INTERNAL_SERVER_ERROR(self, method, url, body, headers):
+ return (httplib.INTERNAL_SERVER_ERROR, "<h1>500: Internal Server Error</h1>", {'content-type': 'text/html'}, httplib.responses[httplib.INTERNAL_SERVER_ERROR])
+
+
if __name__ == '__main__':
sys.exit(unittest.main())
Modified: libcloud/trunk/test/file_fixtures.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/file_fixtures.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/test/file_fixtures.py (original)
+++ libcloud/trunk/test/file_fixtures.py Sat Sep 17 23:35:45 2011
@@ -22,6 +22,7 @@ FIXTURES_ROOT = {
'compute': 'compute/fixtures',
'storage': 'storage/fixtures',
'loadbalancer': 'loadbalancer/fixtures',
+ 'openstack': 'openstack/fixtures',
}
class FileFixtures(object):
@@ -53,3 +54,8 @@ class LoadBalancerFileFixtures(FileFixtu
def __init__(self, sub_dir=''):
super(LoadBalancerFileFixtures, self).__init__(fixtures_type='loadbalancer',
sub_dir=sub_dir)
+
+class OpenStackFixtures(FileFixtures):
+ def __init__(self, sub_dir=''):
+ super(OpenStackFixtures, self).__init__(fixtures_type='openstack',
+ sub_dir=sub_dir)
Modified: libcloud/trunk/test/loadbalancer/test_rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/test_rackspace.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/test/loadbalancer/test_rackspace.py (original)
+++ libcloud/trunk/test/loadbalancer/test_rackspace.py Sat Sep 17 23:35:45 2011
@@ -27,7 +27,7 @@ from libcloud.loadbalancer.drivers.racks
from libcloud.loadbalancer.drivers.rackspace import RackspaceUKLBDriver
from test import MockHttpTestCase
-from test.file_fixtures import LoadBalancerFileFixtures
+from test.file_fixtures import LoadBalancerFileFixtures, OpenStackFixtures
class RackspaceLBTests(unittest.TestCase):
@@ -110,6 +110,7 @@ class RackspaceUKLBTests(RackspaceLBTest
class RackspaceLBMockHttp(MockHttpTestCase):
fixtures = LoadBalancerFileFixtures('rackspace')
+ auth_fixtures = OpenStackFixtures()
def _v1_0(self, method, url, body, headers):
headers = {'x-server-management-url': 'https://servers.api.rackspacecloud.com/v1.0/slug',
@@ -166,5 +167,10 @@ class RackspaceLBMockHttp(MockHttpTestCa
raise NotImplementedError
+ def _v1_1__auth(self, method, url, body, headers):
+ headers = { 'content-type': 'application/json; charset=UTF-8'}
+ body = self.auth_fixtures.load('_v1_1__auth.json')
+ return (httplib.OK, body, headers, httplib.responses[httplib.OK])
+
if __name__ == "__main__":
sys.exit(unittest.main())
Added: libcloud/trunk/test/openstack/fixtures/_v1_1__auth.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/openstack/fixtures/_v1_1__auth.json?rev=1172148&view=auto
==============================================================================
--- libcloud/trunk/test/openstack/fixtures/_v1_1__auth.json (added)
+++ libcloud/trunk/test/openstack/fixtures/_v1_1__auth.json Sat Sep 17 23:35:45 2011
@@ -0,0 +1 @@
+{"auth":{"token":{"id":"603d2bd9-f45c-4583-b91c-2c8eac0b5654","expires":"2011-09-18T02:44:17.000-05:00"},"serviceCatalog":{"cloudFilesCDN":[{"region":"ORD","publicURL":"https:\/\/cdn2.clouddrive.com\/v1\/MossoCloudFS","v1Default":true}],"cloudFiles":[{"region":"ORD","publicURL":"https:\/\/storage101.ord1.clouddrive.com\/v1\/MossoCloudFS","v1Default":true,"internalURL":"https:\/\/snet-storage101.ord1.clouddrive.com\/v1\/MossoCloudFS"}],"cloudServers":[{"publicURL":"https:\/\/servers.api.rackspacecloud.com\/v1.0\/slug","v1Default":true}]}}}
Added: libcloud/trunk/test/openstack/fixtures/_v1_1__auth_mssing_token.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/openstack/fixtures/_v1_1__auth_mssing_token.json?rev=1172148&view=auto
==============================================================================
--- libcloud/trunk/test/openstack/fixtures/_v1_1__auth_mssing_token.json (added)
+++ libcloud/trunk/test/openstack/fixtures/_v1_1__auth_mssing_token.json Sat Sep 17 23:35:45 2011
@@ -0,0 +1 @@
+{"auth":{"token":{"expires":"2011-09-18T02:44:17.000-05:00"},"serviceCatalog":{"cloudFilesCDN":[{"region":"ORD","publicURL":"https:\/\/cdn2.clouddrive.com\/v1\/MossoCloudFS","v1Default":true}],"cloudFiles":[{"region":"ORD","publicURL":"https:\/\/storage101.ord1.clouddrive.com\/v1\/MossoCloudFS","v1Default":true,"internalURL":"https:\/\/snet-storage101.ord1.clouddrive.com\/v1\/MossoCloudFS"}],"cloudServers":[{"publicURL":"https:\/\/servers.api.rackspacecloud.com\/v1.0\/slug","v1Default":true}]}}}
Added: libcloud/trunk/test/openstack/fixtures/_v1_1__auth_unauthorized.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/openstack/fixtures/_v1_1__auth_unauthorized.json?rev=1172148&view=auto
==============================================================================
--- libcloud/trunk/test/openstack/fixtures/_v1_1__auth_unauthorized.json (added)
+++ libcloud/trunk/test/openstack/fixtures/_v1_1__auth_unauthorized.json Sat Sep 17 23:35:45 2011
@@ -0,0 +1 @@
+{"unauthorized":{"message":"Username or api key is invalid","code":401}}
\ No newline at end of file
Modified: libcloud/trunk/test/storage/test_cloudfiles.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/storage/test_cloudfiles.py?rev=1172148&r1=1172147&r2=1172148&view=diff
==============================================================================
--- libcloud/trunk/test/storage/test_cloudfiles.py (original)
+++ libcloud/trunk/test/storage/test_cloudfiles.py Sat Sep 17 23:35:45 2011
@@ -33,7 +33,7 @@ from libcloud.storage.drivers.cloudfiles
from libcloud.storage.drivers.dummy import DummyIterator
from test import StorageMockHttp, MockRawResponse # pylint: disable-msg=E0611
-from test.file_fixtures import StorageFileFixtures # pylint: disable-msg=E0611
+from test.file_fixtures import StorageFileFixtures, OpenStackFixtures # pylint: disable-msg=E0611
current_hash = None
@@ -426,6 +426,7 @@ class CloudFilesTests(unittest.TestCase)
class CloudFilesMockHttp(StorageMockHttp):
fixtures = StorageFileFixtures('cloudfiles')
+ auth_fixtures = OpenStackFixtures()
base_headers = { 'content-type': 'application/json; charset=UTF-8'}
# fake auth token response
@@ -625,6 +626,11 @@ class CloudFilesMockHttp(StorageMockHttp
return (status_code, body, headers, httplib.responses[httplib.OK])
+ def _v1_1__auth(self, method, url, body, headers):
+ body = self.auth_fixtures.load('_v1_1__auth.json')
+ return (httplib.OK, body, {'content-type': 'application/json; charset=UTF-8'}, httplib.responses[httplib.OK])
+
+
class CloudFilesMockRawResponse(MockRawResponse):
fixtures = StorageFileFixtures('cloudfiles')