libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From to...@apache.org
Subject svn commit: r1442533 - in /libcloud/trunk: ./ libcloud/common/ libcloud/compute/drivers/ libcloud/dns/drivers/ libcloud/test/compute/ libcloud/test/compute/fixtures/softlayer/ libcloud/test/dns/
Date Tue, 05 Feb 2013 10:59:52 GMT
Author: tomaz
Date: Tue Feb  5 10:59:52 2013
New Revision: 1442533

URL: http://svn.apache.org/viewvc?rev=1442533&view=rev
Log:
Add a common module (libcloud.common.xmlrpc) for handling XML-RPC
requests using Libcloud http layer.

Also refactor existing drivers which use xmlrpclib directly (VCL, Gandi,
Softlayer) to use this module.

This change allows drivers to support LIBCLOUD_DEBUG and SSL certificate
validation functionality. Previously they have bypassed Libcloud http
layer so this functionality was not available.

Contributed by John Carr, part of LIBCLOUD-288.

Added:
    libcloud/trunk/libcloud/common/xmlrpc.py
    libcloud/trunk/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml
    libcloud/trunk/libcloud/test/compute/fixtures/softlayer/fail.xml
Modified:
    libcloud/trunk/CHANGES
    libcloud/trunk/libcloud/common/gandi.py
    libcloud/trunk/libcloud/compute/drivers/softlayer.py
    libcloud/trunk/libcloud/compute/drivers/vcl.py
    libcloud/trunk/libcloud/dns/drivers/gandi.py
    libcloud/trunk/libcloud/test/compute/test_softlayer.py
    libcloud/trunk/libcloud/test/compute/test_vcl.py
    libcloud/trunk/libcloud/test/dns/test_gandi.py

Modified: libcloud/trunk/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1442533&r1=1442532&r2=1442533&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Tue Feb  5 10:59:52 2013
@@ -27,6 +27,17 @@ Changes with Apache Libcloud in developm
       CA file which is used to verifying the server certificate. (LIBCLOUD-283)
       [Tomaz Muraus, Erinn Looney-Triggs]
 
+    - Add a common module (libcloud.common.xmlrpc) for handling XML-RPC
+      requests using Libcloud http layer.
+
+      Also refactor existing drivers which use xmlrpclib directly (VCL, Gandi,
+      Softlayer) to use this module.
+
+      This change allows drivers to support LIBCLOUD_DEBUG and SSL certificate
+      validation functionality. Previously they have bypassed Libcloud http
+      layer so this functionality was not available. (LIBCLOUD-288)
+      [John Carr]
+
   *) Compute
 
     - Fix string interpolation bug in __repr__ methods in the IBM SCE driver.
@@ -133,15 +144,6 @@ Changes with Apache Libcloud in developm
      Also update pricing to reflect new (decreased) prices.
      [Tomaz Muraus]
 
-   - Modify Gandi.net driver to use Libcloud http(s) layer when performing
-     http requests using xmlrpclib.
-
-     This change allows driver to support LIBCLOUD_DEBUG and SSL vertificate
-     validation functionality. Previously it used xmlrpclib directly which means
-     it bypassed Libcloud's http(s) layer and didn't support previously
-     mentioned features. (LIBCLOUD-288)
-     [John Carr]
-
   *) Storage
 
     - Add a new local storage driver.

Modified: libcloud/trunk/libcloud/common/gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/gandi.py?rev=1442533&r1=1442532&r2=1442533&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/gandi.py (original)
+++ libcloud/trunk/libcloud/common/gandi.py Tue Feb  5 10:59:52 2013
@@ -20,14 +20,13 @@ import time
 import hashlib
 import sys
 
-from libcloud.utils.py3 import xmlrpclib
 from libcloud.utils.py3 import b
 
-from libcloud.common.base import Response, ConnectionKey
+from libcloud.common.base import ConnectionKey
+from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection
 
 # Global constants
 
-
 DEFAULT_TIMEOUT = 600   # operation pooling max seconds
 DEFAULT_INTERVAL = 20   # seconds between 2 operation.info
 
@@ -43,51 +42,24 @@ class GandiException(Exception):
         return '<GandiException code %u "%s">' % (self.args[0], self.args[1])
 
 
-class GandiResponse(Response):
+class GandiResponse(XMLRPCResponse):
     """
     A Base Gandi Response class to derive from.
     """
 
-    def parse_body(self):
-        try:
-            params, methodname = xmlrpclib.loads(self.body)
-
-            if len(params) == 1:
-                return params[0]
-
-            return params
-        except xmlrpclib.Fault:
-            e = sys.exc_info()[1]
-            self.parse_error(e.faultCode, e.faultString)
-            raise GandiException(1000, e)
-
-    def parse_error(self, code=None, message=None):
-        """
-        This hook allows you to inspect any xmlrpclib errors and
-        potentially raise a more useful and specific exception.
-        """
-        pass
-
 
-class GandiConnection(ConnectionKey):
+class GandiConnection(XMLRPCConnection, ConnectionKey):
     """
     Connection class for the Gandi driver
     """
 
     responseCls = GandiResponse
     host = 'rpc.gandi.net'
+    endpoint = '/xmlrpc/'
 
     def request(self, method, *args):
-        """ Request xmlrpc method with given args"""
         args = (self.key, ) + args
-        data = xmlrpclib.dumps(args, methodname=method, allow_none=True)
-        headers = {
-            'Content-Type': 'text/xml',
-        }
-        return super(GandiConnection, self).request('/xmlrpc/',
-                                                    data=data,
-                                                    headers=headers,
-                                                    method='POST')
+        return super(GandiConnection, self).request(method, *args)
 
 
 class BaseGandiDriver(object):

Added: libcloud/trunk/libcloud/common/xmlrpc.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/xmlrpc.py?rev=1442533&view=auto
==============================================================================
--- libcloud/trunk/libcloud/common/xmlrpc.py (added)
+++ libcloud/trunk/libcloud/common/xmlrpc.py Tue Feb  5 10:59:52 2013
@@ -0,0 +1,108 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+Base classes for working with xmlrpc APIs
+"""
+
+import sys
+
+from libcloud.utils.py3 import xmlrpclib
+from libcloud.utils.py3 import httplib
+from libcloud.common.base import Response, Connection
+
+
+class ProtocolError(Exception):
+    pass
+
+
+class ErrorCodeMixin(object):
+    """
+    This is a helper for API's that have a well defined collection of error
+    codes that are easily parsed out of error messages. It acts as a factory:
+    it finds the right exception for the error code, fetches any parameters it
+    needs from the context and raises it.
+    """
+
+    exceptions = {}
+
+    def raise_exception_for_error(self, error_code, message):
+        exceptionCls = self.exceptions.get(error_code, None)
+        if exceptionCls is None:
+            return
+        context = self.connection.context
+        driver = self.connection.driver
+        params = {}
+        if hasattr(exceptionCls, 'kwargs'):
+            for key in exceptionCls.kwargs:
+                if key in context:
+                    params[key] = context[key]
+        raise exceptionCls(value=message, driver=driver, **params)
+
+
+class XMLRPCResponse(ErrorCodeMixin, Response):
+
+    defaultExceptionCls = Exception
+
+    def success(self):
+        return self.status == httplib.OK
+
+    def parse_body(self):
+        try:
+            params, methodname = xmlrpclib.loads(self.body)
+            if len(params) == 1:
+                params = params[0]
+            return params
+        except xmlrpclib.Fault:
+            e = sys.exc_info()[1]
+            self.raise_exception_for_error(e.faultCode, e.faultString)
+            error_string = '%s: %s' % (e.faultCode, e.faultString)
+            raise self.defaultExceptionCls(error_string)
+
+    def parse_error(self):
+        msg = 'Server returned an invalid xmlrpc response (%d)' % (self.status)
+        raise ProtocolError(msg)
+
+
+class XMLRPCConnection(Connection):
+    """
+    Connection class which can call XMLRPC based API's.
+
+    This class uses the xmlrpclib marshalling and demarshalling code but uses
+    the http transports provided by libcloud giving it better certificate
+    validation and debugging helpers than the core client library.
+    """
+
+    responseCls = XMLRPCResponse
+
+    def add_default_headers(self, headers):
+        headers['Content-Type'] = 'text/xml'
+        return headers
+
+    def request(self, method_name, *args, **kwargs):
+        """
+        Call a given `method_name`.
+
+        @type method_name: C{str}
+        @param method_name: A method exposed by the xmlrpc endpoint that you
+            are connecting to.
+
+        @type args: C{tuple}
+        @param args: Arguments to invoke with method with.
+        """
+        endpoint = kwargs.get('endpoint', self.endpoint)
+        data = xmlrpclib.dumps(args, methodname=method_name, allow_none=True)
+        return super(XMLRPCConnection, self).request(endpoint,
+                                                     data=data,
+                                                     method='POST')

Modified: libcloud/trunk/libcloud/compute/drivers/softlayer.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/softlayer.py?rev=1442533&r1=1442532&r2=1442533&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/softlayer.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/softlayer.py Tue Feb  5 10:59:52 2013
@@ -23,6 +23,8 @@ import libcloud
 
 from libcloud.utils.py3 import xmlrpclib
 
+from libcloud.common.base import ConnectionUserAndKey
+from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.compute.types import Provider, NodeState
 from libcloud.compute.base import NodeDriver, Node, NodeLocation, NodeSize, \
@@ -97,78 +99,36 @@ class SoftLayerException(LibcloudError):
     pass
 
 
-class SoftLayerSafeTransport(xmlrpclib.SafeTransport):
-    pass
-
-
-class SoftLayerTransport(xmlrpclib.Transport):
-    pass
-
-
-class SoftLayerProxy(xmlrpclib.ServerProxy):
-    transportCls = (SoftLayerTransport, SoftLayerSafeTransport)
-    API_PREFIX = 'https://api.softlayer.com/xmlrpc/v3/'
-
-    def __init__(self, service, user_agent, verbose=False):
-        cls = self.transportCls[0]
-        if SoftLayerProxy.API_PREFIX[:8] == 'https://':
-            cls = self.transportCls[1]
-        t = cls(use_datetime=0)
-        t.user_agent = user_agent
-        xmlrpclib.ServerProxy.__init__(
-            self,
-            uri='%s/%s' % (SoftLayerProxy.API_PREFIX, service),
-            transport=t,
-            verbose=verbose,
-        )
-
-
-class SoftLayerConnection(object):
-    """
-    Connection class for the SoftLayer driver
-    """
+class SoftLayerResponse(XMLRPCResponse):
+    defaultExceptionCls = SoftLayerException
+    exceptions = {
+        'SoftLayer_Account': InvalidCredsError,
+    }
 
-    proxyCls = SoftLayerProxy
-    driver = None
 
-    def __init__(self, user, key):
-        self.user = user
-        self.key = key
-        self.ua = []
+class SoftLayerConnection(XMLRPCConnection, ConnectionUserAndKey):
+    responseCls = SoftLayerResponse
+    endpoint = '/xmlrpc/v3/'
 
     def request(self, service, method, *args, **kwargs):
-        sl = self.proxyCls(service, self._user_agent())
-
         headers = {}
         headers.update(self._get_auth_headers())
         headers.update(self._get_init_params(service, kwargs.get('id')))
         headers.update(
             self._get_object_mask(service, kwargs.get('object_mask')))
-
         headers.update(
             self._get_object_mask(service, kwargs.get('object_mask')))
-        params = [{'headers': headers}] + list(args)
 
-        try:
-            return getattr(sl, method)(*params)
-        except xmlrpclib.Fault:
-            e = sys.exc_info()[1]
-            if e.faultCode == 'SoftLayer_Account':
-                raise InvalidCredsError(e.faultString)
-            raise SoftLayerException(e)
-
-    def _user_agent(self):
-        return 'libcloud/%s (%s)%s' % (libcloud.__version__,
-                                       self.driver.name,
-                                       ''.join([' (%s)' % x for x in self.ua]))
+        args = ({'headers': headers}, ) + args
+        endpoint = '%s/%s' % (self.endpoint, service)
 
-    def user_agent_append(self, s):
-        self.ua.append(s)
+        return super(SoftLayerConnection, self).request(method, *args,
+                                                        endpoint=endpoint)
 
     def _get_auth_headers(self):
         return {
             'authenticate': {
-                'username': self.user,
+                'username': self.user_id,
                 'apiKey': self.key
             }
         }
@@ -208,24 +168,6 @@ class SoftLayerNodeDriver(NodeDriver):
 
     features = {'create_node': ['generates_password']}
 
-    def __init__(self, key, secret=None, secure=False):
-        """
-        @param    key:    API key or username to used (required)
-        @type     key:    C{str}
-
-        @param    secret: Secret password to be used (required)
-        @type     secret: C{str}
-
-        @param    secure: Weither to use HTTPS or HTTP.
-        @type     secure: C{bool}
-
-        @rtype: C{None}
-        """
-        self.key = key
-        self.secret = secret
-        self.connection = self.connectionCls(key, secret)
-        self.connection.driver = self
-
     def _to_node(self, host):
         try:
             password = \
@@ -283,7 +225,7 @@ class SoftLayerNodeDriver(NodeDriver):
                 'getObject',
                 id=node_id,
                 object_mask=mask
-            )
+            ).object
 
             if res.get('provisionDate', None):
                 return res
@@ -385,7 +327,7 @@ class SoftLayerNodeDriver(NodeDriver):
 
         res = self.connection.request(
             'SoftLayer_Virtual_Guest', 'createObject', newCCI
-        )
+        ).object
 
         node_id = res['id']
         raw_node = self._get_order_information(node_id)
@@ -402,7 +344,7 @@ class SoftLayerNodeDriver(NodeDriver):
     def list_images(self, location=None):
         result = self.connection.request(
             'SoftLayer_Virtual_Guest', 'getCreateObjectOptions'
-        )
+        ).object
         return [self._to_image(i) for i in result['operatingSystems']]
 
     def _to_size(self, id, size):
@@ -429,7 +371,7 @@ class SoftLayerNodeDriver(NodeDriver):
     def list_locations(self):
         res = self.connection.request(
             'SoftLayer_Location_Datacenter', 'getDatacenters'
-        )
+        ).object
         return [self._to_loc(l) for l in res]
 
     def list_nodes(self):
@@ -444,5 +386,5 @@ class SoftLayerNodeDriver(NodeDriver):
             "SoftLayer_Account",
             "getVirtualGuests",
             object_mask=mask
-        )
+        ).object
         return [self._to_node(h) for h in res]

Modified: libcloud/trunk/libcloud/compute/drivers/vcl.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/vcl.py?rev=1442533&r1=1442532&r2=1442533&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/vcl.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/vcl.py Tue Feb  5 10:59:52 2013
@@ -16,89 +16,30 @@
 VCL driver
 """
 
-import sys
 import time
 
-from libcloud.utils.py3 import xmlrpclib
-
+from libcloud.common.base import ConnectionUserAndKey
+from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.compute.types import Provider, NodeState
 from libcloud.compute.base import NodeDriver, Node
 from libcloud.compute.base import NodeSize, NodeImage
 
 
-class VCLSafeTransport(xmlrpclib.SafeTransport):
-    def __init__(self, datetime, user, passwd, host):
-
-        self._pass = passwd
-        self._use_datetime = datetime
-        self._connection = (None, None)
-        self._extra_headers = []
-
-    def send_content(self, connection, request_body):
-        connection.putheader('Content-Type', 'text/xml')
-        connection.putheader('X-APIVERSION', '2')
-        connection.putheader('X-User', self._user)
-        connection.putheader('X-Pass', self._pass)
-        connection.putheader('Content-Length', str(len(request_body)))
-        connection.endheaders(request_body)
-
-
-class VCLProxy(xmlrpclib.ServerProxy):
-    API_POSTFIX = '/index.php?mode=xmlrpccall'
-    transportCls = VCLSafeTransport
-
-    def __init__(self, user, key, secure, host, port, driver, verbose=False):
-        url = ''
-        cls = self.transportCls
-
-        if secure:
-            url = 'https://'
-            port = port or 443
-        else:
-            url = 'http://'
-            port = port or 80
-
-        url += host + ':' + str(port)
-        url += VCLProxy.API_POSTFIX
-
-        self.API = url
-        t = cls(0, user, key, self.API)
-
-        xmlrpclib.ServerProxy.__init__(
-            self,
-            uri=self.API,
-            transport=t,
-            verbose=verbose
-        )
-
-
-class VCLConnection(object):
-    """
-    Connection class for the VCL driver
-    """
+class VCLResponse(XMLRPCResponse):
+    exceptions = {
+        'VCL_Account': InvalidCredsError,
+    }
 
-    proxyCls = VCLProxy
-    driver = None
 
-    def __init__(self, user, key, secure, host, port):
-        self.user = user
-        self.key = key
-        self.secure = secure
-        self.host = host
-        self.port = port
-
-    def request(self, method, *args, **kwargs):
-        sl = self.proxyCls(user=self.user, key=self.key, secure=self.secure,
-                           host=self.host, port=self.port, driver=self.driver)
+class VCLConnection(XMLRPCConnection, ConnectionUserAndKey):
+    endpoint = '/index.php?mode=xmlrpccall'
 
-        try:
-            return getattr(sl, method)(*args)
-        except xmlrpclib.Fault:
-            e = sys.exc_info()[1]
-            if e.faultCode == 'VCL_Account':
-                raise InvalidCredsError(e.faultString)
-            raise LibcloudError(e, driver=self.driver)
+    def add_default_headers(self, headers):
+        headers['X-APIVERSION'] = '2'
+        headers['X-User'] = self.user_id
+        headers['X-Pass'] = self.key
+        return headers
 
 
 class VCLNodeDriver(NodeDriver):
@@ -151,17 +92,15 @@ class VCLNodeDriver(NodeDriver):
             raise Exception('When instantiating VCL driver directly ' +
                             'you also need to provide host')
 
-        self.key = key
-        self.host = host
-        self.secret = secret
-        self.connection = self.connectionCls(key, secret, secure, host, port)
-        self.connection.driver = self
+        super(VCLNodeDriver, self).__init__(key, secret, secure=True,
+                                            host=None, port=None, *args,
+                                            **kwargs)
 
     def _vcl_request(self, method, *args):
         res = self.connection.request(
             method,
             *args
-        )
+        ).object
         if(res['status'] == 'error'):
             raise LibcloudError(res['errormsg'], driver=self)
         return res
@@ -237,7 +176,7 @@ class VCLNodeDriver(NodeDriver):
         """
         res = self.connection.request(
             "XMLRPCgetImages"
-        )
+        ).object
         return [self._to_image(i) for i in res]
 
     def list_sizes(self, location=None):

Modified: libcloud/trunk/libcloud/dns/drivers/gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/gandi.py?rev=1442533&r1=1442532&r2=1442533&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/gandi.py (original)
+++ libcloud/trunk/libcloud/dns/drivers/gandi.py Tue Feb  5 10:59:52 2013
@@ -65,14 +65,9 @@ class NewZoneVersion(object):
 
 
 class GandiDNSResponse(GandiResponse):
-
-    def parse_error(self, code, message):
-        context = self.connection.context
-        driver = self.connection.driver
-        if code == 581042:
-            zone_id = str(context.get('zone_id', None))
-            raise ZoneDoesNotExistError(value='', driver=driver,
-                                        zone_id=zone_id)
+    exceptions = {
+        581042: ZoneDoesNotExistError,
+    }
 
 
 class GandiDNSConnection(GandiConnection):
@@ -107,7 +102,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
 
     def _to_zone(self, zone):
         return Zone(
-            id=zone['id'],
+            id=str(zone['id']),
             domain=zone['name'],
             type='master',
             ttl=0,
@@ -127,7 +122,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
 
     def get_zone(self, zone_id):
         zid = int(zone_id)
-        self.connection.set_context({'zone_id': zid})
+        self.connection.set_context({'zone_id': zone_id})
         zone = self.connection.request('domain.zone.info', zid)
         return self._to_zone(zone.object)
 
@@ -141,13 +136,13 @@ class GandiDNSDriver(BaseGandiDriver, DN
     def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None):
         zid = int(zone.id)
         params = {'name': domain}
-        self.connection.set_context({'zone_id': zid})
+        self.connection.set_context({'zone_id': zone.id})
         zone = self.connection.request('domain.zone.update', zid, params)
         return self._to_zone(zone.object)
 
     def delete_zone(self, zone):
         zid = int(zone.id)
-        self.connection.set_context({'zone_id': zid})
+        self.connection.set_context({'zone_id': zone.id})
         res = self.connection.request('domain.zone.delete', zid)
         return res.object
 
@@ -170,7 +165,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
 
     def list_records(self, zone):
         zid = int(zone.id)
-        self.connection.set_context({'zone_id': zid})
+        self.connection.set_context({'zone_id': zone.id})
         records = self.connection.request('domain.zone.record.list', zid, 0)
         return self._to_records(records.object, zone)
 
@@ -181,7 +176,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
             'name': name,
             'type': record_type
         }
-        self.connection.set_context({'zone_id': zid})
+        self.connection.set_context({'zone_id': zone_id})
         records = self.connection.request('domain.zone.record.list',
                                           zid, 0, filter_opts).object
 
@@ -219,7 +214,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
 
         with NewZoneVersion(self, zone) as vid:
             con = self.connection
-            con.set_context({'zone_id': zid})
+            con.set_context({'zone_id': zone.id})
             rec = con.request('domain.zone.record.add',
                               zid, vid, create).object
 
@@ -246,7 +241,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
 
         with NewZoneVersion(self, record.zone) as vid:
             con = self.connection
-            con.set_context({'zone_id': zid})
+            con.set_context({'zone_id': record.zone.id})
             con.request('domain.zone.record.delete',
                         zid, vid, filter_opts)
             res = con.request('domain.zone.record.add',
@@ -264,7 +259,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
 
         with NewZoneVersion(self, record.zone) as vid:
             con = self.connection
-            con.set_context({'zone_id': zid})
+            con.set_context({'zone_id': record.zone.id})
             count = con.request('domain.zone.record.delete',
                                 zid, vid, filter_opts).object
 

Added: libcloud/trunk/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml?rev=1442533&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml (added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml Tue Feb
 5 10:59:52 2013
@@ -0,0 +1,17 @@
+<?xml version='1.0'?>
+<methodResponse>
+  <fault>
+    <value>
+      <struct>
+        <member>
+          <name>faultCode</name>
+          <value><string>SoftLayer_Account</string></value>
+        </member>
+        <member>
+          <name>faultString</name>
+          <value><string>Failed Call</string></value>
+        </member>
+      </struct>
+    </value>
+  </fault>
+</methodResponse>

Added: libcloud/trunk/libcloud/test/compute/fixtures/softlayer/fail.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/softlayer/fail.xml?rev=1442533&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/softlayer/fail.xml (added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/softlayer/fail.xml Tue Feb  5 10:59:52 2013
@@ -0,0 +1,17 @@
+<?xml version='1.0'?>
+<methodResponse>
+  <fault>
+    <value>
+      <struct>
+        <member>
+          <name>faultCode</name>
+          <value><string>fail</string></value>
+        </member>
+        <member>
+          <name>faultString</name>
+          <value><string>Failed Call</string></value>
+        </member>
+      </struct>
+    </value>
+  </fault>
+</methodResponse>

Modified: libcloud/trunk/libcloud/test/compute/test_softlayer.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_softlayer.py?rev=1442533&r1=1442532&r2=1442533&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_softlayer.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_softlayer.py Tue Feb  5 10:59:52 2013
@@ -34,33 +34,12 @@ from libcloud.test.file_fixtures import 
 from libcloud.test.secrets import SOFTLAYER_PARAMS
 
 
-class MockSoftLayerTransport(xmlrpclib.Transport):
-
-    def request(self, host, handler, request_body, verbose=0):
-        self.verbose = 0
-
-        if 'SOFTLAYEREXCEPTION' in u(request_body):
-            raise xmlrpclib.Fault('fail', 'Failed Call')
-        if 'INVALIDCREDSERROR' in u(request_body):
-            raise xmlrpclib.Fault('SoftLayer_Account', 'Failed Call')
-
-        method = ET.XML(request_body).find('methodName').text
-        mock = SoftLayerMockHttp(host, 80)
-        mock.request('POST', "%s/%s" % (handler, method))
-        resp = mock.getresponse()
-
-        if sys.version[0] == '2' and sys.version[2] == '7':
-            response = self.parse_response(resp)
-        else:
-            response = self.parse_response(resp.body)
-        return response
-
-
 class SoftLayerTests(unittest.TestCase):
 
     def setUp(self):
-        SoftLayer.connectionCls.proxyCls.transportCls = [
-            MockSoftLayerTransport, MockSoftLayerTransport]
+        SoftLayer.connectionCls.conn_classes = (
+            SoftLayerMockHttp, SoftLayerMockHttp)
+        SoftLayerMockHttp.type = None
         self.driver = SoftLayer(*SOFTLAYER_PARAMS)
 
     def test_list_nodes(self):
@@ -94,6 +73,7 @@ class SoftLayerTests(unittest.TestCase):
                                 image=self.driver.list_images()[0])
 
     def test_create_fail(self):
+        SoftLayerMockHttp.type = "SOFTLAYEREXCEPTION"
         self.assertRaises(
             SoftLayerException,
             self.driver.create_node,
@@ -103,6 +83,7 @@ class SoftLayerTests(unittest.TestCase):
             image=self.driver.list_images()[0])
 
     def test_create_creds_error(self):
+        SoftLayerMockHttp.type = "INVALIDCREDSERROR"
         self.assertRaises(
             InvalidCredsError,
             self.driver.create_node,
@@ -153,6 +134,15 @@ class SoftLayerTests(unittest.TestCase):
 class SoftLayerMockHttp(MockHttp):
     fixtures = ComputeFileFixtures('softlayer')
 
+    def _get_method_name(self, type, use_param, qs, path):
+        return "_xmlrpc"
+
+    def _xmlrpc(self, method, url, body, headers):
+        params, meth_name = xmlrpclib.loads(body)
+        url = url.replace("/", "_")
+        meth_name = "%s_%s" % (url, meth_name)
+        return getattr(self, meth_name)(method, url, body, headers)
+
     def _xmlrpc_v3__SoftLayer_Virtual_Guest_getCreateObjectOptions(
             self, method, url, body, headers):
         body = self.fixtures.load(
@@ -172,8 +162,12 @@ class SoftLayerMockHttp(MockHttp):
 
     def _xmlrpc_v3__SoftLayer_Virtual_Guest_createObject(
             self, method, url, body, headers):
-        body = self.fixtures.load(
-            'v3__SoftLayer_Virtual_Guest_createObject.xml')
+        fixture = {
+            None: 'v3__SoftLayer_Virtual_Guest_createObject.xml',
+            'INVALIDCREDSERROR': 'SoftLayer_Account.xml',
+            'SOFTLAYEREXCEPTION': 'fail.xml',
+        }[self.type]
+        body = self.fixtures.load(fixture)
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _xmlrpc_v3__SoftLayer_Virtual_Guest_getObject(
@@ -192,5 +186,6 @@ class SoftLayerMockHttp(MockHttp):
         body = self.fixtures.load('empty.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+
 if __name__ == '__main__':
     sys.exit(unittest.main())

Modified: libcloud/trunk/libcloud/test/compute/test_vcl.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_vcl.py?rev=1442533&r1=1442532&r2=1442533&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_vcl.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_vcl.py Tue Feb  5 10:59:52 2013
@@ -29,31 +29,13 @@ from libcloud.test import MockHttp
 from libcloud.test.file_fixtures import ComputeFileFixtures
 from libcloud.test.secrets import VCL_PARAMS
 
-class MockVCLTransport(xmlrpclib.Transport):
-
-    def __init__(self, datetime, user, passwd, host):
-        self._use_datetime = datetime
-        self._connection = (None, None)
-        self._extra_headers = []
-        self._use_builtin_types = False
-
-    def request(self, host, handler, request_body, verbose=0):
-        self.verbose = 0
-        method = ET.XML(request_body).find('methodName').text
-        mock = VCLMockHttp(host, 80)
-        mock.request('POST', method)
-        resp = mock.getresponse()
-
-        if sys.version[0] == '2' and sys.version[2] == '7':
-            response = self.parse_response(resp)
-        else:
-            response = self.parse_response(resp.body)
-        return response
 
 class VCLTests(unittest.TestCase):
 
     def setUp(self):
-        VCL.connectionCls.proxyCls.transportCls = MockVCLTransport
+        VCL.connectionCls.conn_classes = (
+            VCLMockHttp, VCLMockHttp)
+        VCLMockHttp.type = None
         self.driver = VCL(*VCL_PARAMS)
 
     def test_list_nodes(self):
@@ -98,50 +80,48 @@ class VCLTests(unittest.TestCase):
             1334168100
         )
 
+
 class VCLMockHttp(MockHttp):
     fixtures = ComputeFileFixtures('vcl')
 
+    def _get_method_name(self, type, use_param, qs, path):
+        return "_xmlrpc"
+
+    def _xmlrpc(self, method, url, body, headers):
+        params, meth_name = xmlrpclib.loads(body)
+        if self.type:
+            meth_name = "%s_%s" % (meth_name, self.type)
+        return getattr(self, meth_name)(method, url, body, headers)
+
     def XMLRPCgetImages(self, method, url, body, headers):
         body = self.fixtures.load('XMLRPCgetImages.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def XMLRPCextendRequest(
-        self, method, url, body, headers):
-
+    def XMLRPCextendRequest(self, method, url, body, headers):
         body = self.fixtures.load('XMLRPCextendRequest.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def XMLRPCgetRequestIds(
-        self, method, url, body, headers):
-
+    def XMLRPCgetRequestIds(self, method, url, body, headers):
         body = self.fixtures.load(
             'XMLRPCgetRequestIds.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def XMLRPCgetRequestStatus(
-        self, method, url, body, headers):
-
+    def XMLRPCgetRequestStatus(self, method, url, body, headers):
         body = self.fixtures.load(
             'XMLRPCgetRequestStatus.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def XMLRPCendRequest(
-        self, method, url, body, headers):
-
+    def XMLRPCendRequest(self, method, url, body, headers):
         body = self.fixtures.load(
             'XMLRPCendRequest.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def XMLRPCaddRequest(
-        self, method, url, body, headers):
-
+    def XMLRPCaddRequest(self, method, url, body, headers):
         body = self.fixtures.load(
             'XMLRPCaddRequest.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def XMLRPCgetRequestConnectData(
-        self, method, url, body, headers):
-
+    def XMLRPCgetRequestConnectData(self, method, url, body, headers):
         body = self.fixtures.load(
             'XMLRPCgetRequestConnectData.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])

Modified: libcloud/trunk/libcloud/test/dns/test_gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/test_gandi.py?rev=1442533&r1=1442532&r2=1442533&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/dns/test_gandi.py (original)
+++ libcloud/trunk/libcloud/test/dns/test_gandi.py Tue Feb  5 10:59:52 2013
@@ -247,39 +247,48 @@ class GandiMockHttp(BaseGandiMockHttp):
         body = self.fixtures.load('new_version.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_record_list_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
+    def _xmlrpc__domain_zone_record_list_ZONE_DOES_NOT_EXIST(self, method, url,
+                                                             body, headers):
         body = self.fixtures.load('zone_doesnt_exist.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_info_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
+    def _xmlrpc__domain_zone_info_ZONE_DOES_NOT_EXIST(self, method, url, body,
+                                                      headers):
         body = self.fixtures.load('zone_doesnt_exist.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_list_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
+    def _xmlrpc__domain_zone_list_ZONE_DOES_NOT_EXIST(self, method, url, body,
+                                                      headers):
         body = self.fixtures.load('zone_doesnt_exist.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_delete_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
+    def _xmlrpc__domain_zone_delete_ZONE_DOES_NOT_EXIST(self, method, url,
+                                                        body, headers):
         body = self.fixtures.load('zone_doesnt_exist.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_record_list_RECORD_DOES_NOT_EXIST(self, method, url, body, headers):
+    def _xmlrpc__domain_zone_record_list_RECORD_DOES_NOT_EXIST(
+            self, method, url, body, headers):
         body = self.fixtures.load('list_records_empty.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_info_RECORD_DOES_NOT_EXIST(self, method, url, body, headers):
+    def _xmlrpc__domain_zone_info_RECORD_DOES_NOT_EXIST(self, method, url,
+                                                        body, headers):
         body = self.fixtures.load('list_zones.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_record_delete_RECORD_DOES_NOT_EXIST(self, method, url, body,
headers):
+    def _xmlrpc__domain_zone_record_delete_RECORD_DOES_NOT_EXIST(
+            self, method, url, body, headers):
         body = self.fixtures.load('delete_record_doesnotexist.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_version_new_RECORD_DOES_NOT_EXIST(self, method, url, body, headers):
+    def _xmlrpc__domain_zone_version_new_RECORD_DOES_NOT_EXIST(
+            self, method, url, body, headers):
         body = self.fixtures.load('new_version.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _xmlrpc__domain_zone_version_set_RECORD_DOES_NOT_EXIST(self, method, url, body, headers):
+    def _xmlrpc__domain_zone_version_set_RECORD_DOES_NOT_EXIST(
+            self, method, url, body, headers):
         body = self.fixtures.load('new_version.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 



Mime
View raw message