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 2013/02/03 20:24:20 UTC
svn commit: r1441956 - in /libcloud/trunk: ./ libcloud/common/
libcloud/compute/drivers/ libcloud/dns/drivers/ libcloud/test/common/
libcloud/test/compute/ libcloud/test/dns/ libcloud/test/dns/fixtures/gandi/
Author: tomaz
Date: Sun Feb 3 19:24:19 2013
New Revision: 1441956
URL: http://svn.apache.org/viewvc?rev=1441956&view=rev
Log:
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.
Contributed by John Carr, part of LIBCLOUD-288.
Added:
libcloud/trunk/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml
Modified:
libcloud/trunk/CHANGES
libcloud/trunk/libcloud/common/gandi.py
libcloud/trunk/libcloud/compute/drivers/gandi.py
libcloud/trunk/libcloud/dns/drivers/gandi.py
libcloud/trunk/libcloud/test/common/test_gandi.py
libcloud/trunk/libcloud/test/compute/test_gandi.py
libcloud/trunk/libcloud/test/dns/test_gandi.py
Modified: libcloud/trunk/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1441956&r1=1441955&r2=1441956&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Sun Feb 3 19:24:19 2013
@@ -133,6 +133,15 @@ 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=1441956&r1=1441955&r2=1441956&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/gandi.py (original)
+++ libcloud/trunk/libcloud/common/gandi.py Sun Feb 3 19:24:19 2013
@@ -23,11 +23,10 @@ import sys
from libcloud.utils.py3 import xmlrpclib
from libcloud.utils.py3 import b
-from libcloud.common.base import ConnectionKey
+from libcloud.common.base import Response, ConnectionKey
# Global constants
-API_URL = "https://rpc.gandi.net/xmlrpc/"
DEFAULT_TIMEOUT = 600 # operation pooling max seconds
DEFAULT_INTERVAL = 20 # seconds between 2 operation.info
@@ -38,65 +37,31 @@ class GandiException(Exception):
Exception class for Gandi driver
"""
def __str__(self):
- return "(%u) %s" % (self.args[0], self.args[1])
+ return '(%u) %s' % (self.args[0], self.args[1])
def __repr__(self):
- return "<GandiException code %u '%s'>" % (self.args[0], self.args[1])
+ return '<GandiException code %u "%s">' % (self.args[0], self.args[1])
-class GandiSafeTransport(xmlrpclib.SafeTransport):
- pass
-
-
-class GandiTransport(xmlrpclib.Transport):
- pass
-
-
-class GandiProxy(xmlrpclib.ServerProxy):
- transportCls = (GandiTransport, GandiSafeTransport)
-
- def __init__(self, user_agent, verbose=0):
- cls = self.transportCls[0]
- if API_URL.startswith("https://"):
- cls = self.transportCls[1]
- t = cls(use_datetime=0)
- t.user_agent = user_agent
- xmlrpclib.ServerProxy.__init__(
- self,
- uri=API_URL,
- transport=t,
- verbose=verbose,
- allow_none=True
- )
-
-
-class GandiConnection(ConnectionKey):
+class GandiResponse(Response):
"""
- Connection class for the Gandi driver
+ A Base Gandi Response class to derive from.
"""
- proxyCls = GandiProxy
-
- def __init__(self, key, password=None):
- super(GandiConnection, self).__init__(key)
- self.driver = BaseGandiDriver
-
+ def parse_body(self):
try:
- self._proxy = self.proxyCls(self._user_agent())
- except xmlrpclib.Fault:
- e = sys.exc_info()[1]
- raise GandiException(1000, e)
+ params, methodname = xmlrpclib.loads(self.body)
- def request(self, method, *args):
- """ Request xmlrpc method with given args"""
- try:
- return getattr(self._proxy, method)(self.key, *args)
+ 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(1001, e.faultString)
+ raise GandiException(1000, e)
- def parse_error(self, code, message):
+ 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.
@@ -104,6 +69,27 @@ class GandiConnection(ConnectionKey):
pass
+class GandiConnection(ConnectionKey):
+ """
+ Connection class for the Gandi driver
+ """
+
+ responseCls = GandiResponse
+ host = 'rpc.gandi.net'
+
+ 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')
+
+
class BaseGandiDriver(object):
"""
Gandi base driver
@@ -112,22 +98,6 @@ class BaseGandiDriver(object):
connectionCls = GandiConnection
name = 'Gandi'
- 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}
- """
- self.key = key
- self.secret = secret
- self.connection = self.connectionCls(key, secret)
- self.connection.driver = self
-
# Specific methods for gandi
def _wait_operation(self, id, timeout=DEFAULT_TIMEOUT,
check_interval=DEFAULT_INTERVAL):
@@ -135,7 +105,7 @@ class BaseGandiDriver(object):
for i in range(0, timeout, check_interval):
try:
- op = self.connection.request('operation.info', int(id))
+ op = self.connection.request('operation.info', int(id)).object
if op['step'] == 'DONE':
return True
@@ -180,7 +150,7 @@ class BaseObject(object):
Note, for example, that this example will always produce the
same UUID!
"""
- hashstring = "%s:%s:%s" % \
+ hashstring = '%s:%s:%s' % \
(self.uuid_prefix, self.id, self.driver.type)
return hashlib.sha1(b(hashstring)).hexdigest()
Modified: libcloud/trunk/libcloud/compute/drivers/gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/gandi.py?rev=1441956&r1=1441955&r2=1441956&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/gandi.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/gandi.py Sun Feb 3 19:24:19 2013
@@ -62,7 +62,7 @@ class GandiNodeDriver(BaseGandiDriver, N
def _resource_info(self, type, id):
try:
obj = self.connection.request('%s.info' % type, int(id))
- return obj
+ return obj.object
except Exception:
e = sys.exc_info()[1]
raise GandiException(1003, e)
@@ -109,8 +109,8 @@ class GandiNodeDriver(BaseGandiDriver, N
return [self._to_volume(d) for d in disks]
def list_nodes(self):
- vms = self.connection.request('vm.list')
- ips = self.connection.request('ip.list')
+ vms = self.connection.request('vm.list').object
+ ips = self.connection.request('ip.list').object
for vm in vms:
vm['ips'] = []
for ip in ips:
@@ -124,7 +124,7 @@ class GandiNodeDriver(BaseGandiDriver, N
def reboot_node(self, node):
op = self.connection.request('vm.reboot', int(node.id))
- self._wait_operation(op['id'])
+ self._wait_operation(op.object['id'])
vm = self._node_info(int(node.id))
if vm['state'] == 'running':
return True
@@ -135,11 +135,11 @@ class GandiNodeDriver(BaseGandiDriver, N
if vm['state'] == 'running':
# Send vm_stop and wait for accomplish
op_stop = self.connection.request('vm.stop', int(node.id))
- if not self._wait_operation(op_stop['id']):
+ if not self._wait_operation(op_stop.object['id']):
raise GandiException(1010, 'vm.stop failed')
# Delete
op = self.connection.request('vm.delete', int(node.id))
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
@@ -221,7 +221,7 @@ class GandiNodeDriver(BaseGandiDriver, N
(op_disk, op_iface, op_vm) = self.connection.request(
'vm.create_from',
vm_spec, disk_spec, src_disk_id
- )
+ ).object
# We wait for vm_create to finish
if self._wait_operation(op_vm['id']):
@@ -251,7 +251,7 @@ class GandiNodeDriver(BaseGandiDriver, N
else:
filtering = {}
images = self.connection.request('image.list', filtering)
- return [self._to_image(i) for i in images]
+ return [self._to_image(i) for i in images.object]
except Exception:
e = sys.exc_info()[1]
raise GandiException(1011, e)
@@ -268,7 +268,7 @@ class GandiNodeDriver(BaseGandiDriver, N
)
def list_sizes(self, location=None):
- account = self.connection.request('account.info')
+ account = self.connection.request('account.info').object
# Look for available shares, and return a list of share_definition
available_res = account['resources']['available']
@@ -306,8 +306,8 @@ class GandiNodeDriver(BaseGandiDriver, N
)
def list_locations(self):
- res = self.connection.request("datacenter.list")
- return [self._to_loc(l) for l in res]
+ res = self.connection.request('datacenter.list')
+ return [self._to_loc(l) for l in res.object]
def list_volumes(self):
"""
@@ -315,7 +315,7 @@ class GandiNodeDriver(BaseGandiDriver, N
@rtype: C{list} of L{StorageVolume}
"""
res = self.connection.request('disk.list', {})
- return self._to_volumes(res)
+ return self._to_volumes(res.object)
def create_volume(self, size, name, location=None, snapshot=None):
disk_param = {
@@ -328,15 +328,15 @@ class GandiNodeDriver(BaseGandiDriver, N
disk_param, int(snapshot.id))
else:
op = self.connection.request('disk.create', disk_param)
- if self._wait_operation(op['id']):
- disk = self._volume_info(op['disk_id'])
+ if self._wait_operation(op.object['id']):
+ disk = self._volume_info(op.object['disk_id'])
return self._to_volume(disk)
return None
def attach_volume(self, node, volume, device=None):
op = self.connection.request('vm.disk_attach',
int(node.id), int(volume.id))
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
@@ -354,13 +354,13 @@ class GandiNodeDriver(BaseGandiDriver, N
"""
op = self.connection.request('vm.disk_detach',
int(node.id), int(volume.id))
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
def destroy_volume(self, volume):
op = self.connection.request('disk.delete', int(volume.id))
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
@@ -401,8 +401,8 @@ class GandiNodeDriver(BaseGandiDriver, N
@rtype: C{list} of L{GandiNetworkInterface}
"""
- ifaces = self.connection.request('iface.list')
- ips = self.connection.request('ip.list')
+ ifaces = self.connection.request('iface.list').object
+ ips = self.connection.request('ip.list').object
for iface in ifaces:
iface['ips'] = list(
filter(lambda i: i['iface_id'] == iface['id'], ips))
@@ -432,7 +432,7 @@ class GandiNodeDriver(BaseGandiDriver, N
@rtype: C{list} of L{GandiDisk}
"""
res = self.connection.request('disk.list', {})
- return self._to_disks(res)
+ return self._to_disks(res.object)
def ex_node_attach_disk(self, node, disk):
"""
@@ -448,7 +448,7 @@ class GandiNodeDriver(BaseGandiDriver, N
"""
op = self.connection.request('vm.disk_attach',
int(node.id), int(disk.id))
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
@@ -466,7 +466,7 @@ class GandiNodeDriver(BaseGandiDriver, N
"""
op = self.connection.request('vm.disk_detach',
int(node.id), int(disk.id))
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
@@ -485,7 +485,7 @@ class GandiNodeDriver(BaseGandiDriver, N
"""
op = self.connection.request('vm.iface_attach',
int(node.id), int(iface.id))
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
@@ -504,7 +504,7 @@ class GandiNodeDriver(BaseGandiDriver, N
"""
op = self.connection.request('vm.iface_detach',
int(node.id), int(iface.id))
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
@@ -521,16 +521,16 @@ class GandiNodeDriver(BaseGandiDriver, N
@rtype: C{bool}
"""
if not disk.extra.get('can_snapshot'):
- raise GandiException(1021, "Disk %s can't snapshot" % disk.id)
+ raise GandiException(1021, 'Disk %s can\'t snapshot' % disk.id)
if not name:
- suffix = datetime.today().strftime("%Y%m%d")
- name = "snap_%s" % (suffix)
+ suffix = datetime.today().strftime('%Y%m%d')
+ name = 'snap_%s' % (suffix)
op = self.connection.request(
'disk.create_from',
{'name': name, 'type': 'snapshot', },
int(disk.id),
)
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
@@ -557,6 +557,6 @@ class GandiNodeDriver(BaseGandiDriver, N
op = self.connection.request('disk.update',
int(disk.id),
params)
- if self._wait_operation(op['id']):
+ if self._wait_operation(op.object['id']):
return True
return False
Modified: libcloud/trunk/libcloud/dns/drivers/gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/gandi.py?rev=1441956&r1=1441955&r2=1441956&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/gandi.py (original)
+++ libcloud/trunk/libcloud/dns/drivers/gandi.py Sun Feb 3 19:24:19 2013
@@ -20,6 +20,7 @@ __all__ = [
]
from libcloud.common.gandi import BaseGandiDriver, GandiConnection
+from libcloud.common.gandi import GandiResponse
from libcloud.dns.types import Provider, RecordType
from libcloud.dns.types import RecordError
from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
@@ -51,7 +52,7 @@ class NewZoneVersion(object):
def __enter__(self):
zid = int(self.zone.id)
self.connection.set_context({'zone_id': self.zone.id})
- vid = self.connection.request('domain.zone.version.new', zid)
+ vid = self.connection.request('domain.zone.version.new', zid).object
self.vid = vid
return vid
@@ -60,18 +61,24 @@ class NewZoneVersion(object):
zid = int(self.zone.id)
con = self.connection
con.set_context({'zone_id': self.zone.id})
- con.request('domain.zone.version.set', zid, self.vid)
+ con.request('domain.zone.version.set', zid, self.vid).object
-class GandiDNSConnection(GandiConnection):
+class GandiDNSResponse(GandiResponse):
def parse_error(self, code, message):
+ context = self.connection.context
+ driver = self.connection.driver
if code == 581042:
- zone_id = str(self.context.get('zone_id', None))
- raise ZoneDoesNotExistError(value='', driver=self.driver,
+ zone_id = str(context.get('zone_id', None))
+ raise ZoneDoesNotExistError(value='', driver=driver,
zone_id=zone_id)
+class GandiDNSConnection(GandiConnection):
+ responseCls = GandiDNSResponse
+
+
class GandiDNSDriver(BaseGandiDriver, DNSDriver):
"""
API reference can be found at:
@@ -116,31 +123,33 @@ class GandiDNSDriver(BaseGandiDriver, DN
def list_zones(self):
zones = self.connection.request('domain.zone.list')
- return self._to_zones(zones)
+ return self._to_zones(zones.object)
def get_zone(self, zone_id):
zid = int(zone_id)
self.connection.set_context({'zone_id': zid})
zone = self.connection.request('domain.zone.info', zid)
- return self._to_zone(zone)
+ return self._to_zone(zone.object)
def create_zone(self, domain, type='master', ttl=None, extra=None):
- params = {'name': domain}
+ params = {
+ 'name': domain,
+ }
info = self.connection.request('domain.zone.create', params)
- return self._to_zone(info)
+ return self._to_zone(info.object)
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})
zone = self.connection.request('domain.zone.update', zid, params)
- return self._to_zone(zone)
+ return self._to_zone(zone.object)
def delete_zone(self, zone):
zid = int(zone.id)
self.connection.set_context({'zone_id': zid})
res = self.connection.request('domain.zone.delete', zid)
- return res
+ return res.object
def _to_record(self, record, zone):
return Record(
@@ -163,7 +172,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
zid = int(zone.id)
self.connection.set_context({'zone_id': zid})
records = self.connection.request('domain.zone.record.list', zid, 0)
- return self._to_records(records, zone)
+ return self._to_records(records.object, zone)
def get_record(self, zone_id, record_id):
zid = int(zone_id)
@@ -174,7 +183,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
}
self.connection.set_context({'zone_id': zid})
records = self.connection.request('domain.zone.record.list',
- zid, 0, filter_opts)
+ zid, 0, filter_opts).object
if len(records) == 0:
raise RecordDoesNotExistError(value='', driver=self,
@@ -212,7 +221,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
con = self.connection
con.set_context({'zone_id': zid})
rec = con.request('domain.zone.record.add',
- zid, vid, create)
+ zid, vid, create).object
return self._to_record(rec, zone)
@@ -241,7 +250,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
con.request('domain.zone.record.delete',
zid, vid, filter_opts)
res = con.request('domain.zone.record.add',
- zid, vid, update)
+ zid, vid, update).object
return self._to_record(res, record.zone)
@@ -257,7 +266,7 @@ class GandiDNSDriver(BaseGandiDriver, DN
con = self.connection
con.set_context({'zone_id': zid})
count = con.request('domain.zone.record.delete',
- zid, vid, filter_opts)
+ zid, vid, filter_opts).object
if count == 1:
return True
Modified: libcloud/trunk/libcloud/test/common/test_gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/common/test_gandi.py?rev=1441956&r1=1441955&r2=1441956&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/common/test_gandi.py (original)
+++ libcloud/trunk/libcloud/test/common/test_gandi.py Sun Feb 3 19:24:19 2013
@@ -1,33 +1,15 @@
-import sys
-import unittest
-
-from xml.etree import ElementTree as ET
-
from libcloud.utils.py3 import xmlrpclib
+from libcloud.test import MockHttp
-class MockGandiTransport(xmlrpclib.Transport):
-
- def request(self, host, handler, request_body, verbose=0):
- self.verbose = 0
- method = ET.XML(request_body).find('methodName').text
- mock = self.mockCls(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 BaseGandiMockHttp(MockHttp):
-class BaseGandiTests(unittest.TestCase):
+ def _get_method_name(self, type, use_param, qs, path):
+ return "_xmlrpc"
- def setUp(self):
- d = self.driverCls
- t = self.transportCls
- t.mockCls.type = None
- d.connectionCls.proxyCls.transportCls = \
- [t, t]
- self.driver = d(*self.params)
+ def _xmlrpc(self, method, url, body, headers):
+ params, methodName = xmlrpclib.loads(body)
+ meth_name = '_xmlrpc__' + methodName.replace('.', '_')
+ if self.type:
+ meth_name = '%s_%s' % (meth_name, self.type)
+ return getattr(self, meth_name)(method, url, body, headers)
Modified: libcloud/trunk/libcloud/test/compute/test_gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_gandi.py?rev=1441956&r1=1441955&r2=1441956&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_gandi.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_gandi.py Sun Feb 3 19:24:19 2013
@@ -19,125 +19,26 @@ import random
import string
from libcloud.utils.py3 import httplib
-from libcloud.utils.py3 import xmlrpclib
from libcloud.compute.drivers.gandi import GandiNodeDriver
-from libcloud.compute.base import StorageVolume
from libcloud.common.gandi import GandiException
from libcloud.compute.types import NodeState
-from xml.etree import ElementTree as ET
-from libcloud.test import MockHttp
from libcloud.test.file_fixtures import ComputeFileFixtures
from libcloud.test.secrets import GANDI_PARAMS
-from libcloud.test.common.test_gandi import MockGandiTransport, BaseGandiTests
+from libcloud.test.common.test_gandi import BaseGandiMockHttp
-class GandiMockHttp(MockHttp):
-
- fixtures = ComputeFileFixtures('gandi')
-
- def _xmlrpc__datacenter_list(self, method, url, body, headers):
- body = self.fixtures.load('datacenter_list.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__image_list(self, method, url, body, headers):
- body = self.fixtures.load('image_list_dc0.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_list(self, method, url, body, headers):
- body = self.fixtures.load('vm_list.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__ip_list(self, method, url, body, headers):
- body = self.fixtures.load('ip_list.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__account_info(self, method, url, body, headers):
- body = self.fixtures.load('account_info.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_info(self, method, url, body, headers):
- body = self.fixtures.load('vm_info.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_delete(self, method, url, body, headers):
- body = self.fixtures.load('vm_delete.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__operation_info(self, method, url, body, headers):
- body = self.fixtures.load('operation_info.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_create_from(self, method, url, body, headers):
- body = self.fixtures.load('vm_create_from.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_reboot(self, method, url, body, headers):
- body = self.fixtures.load('vm_reboot.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_stop(self, method, url, body, headers):
- body = self.fixtures.load('vm_stop.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__iface_list(self, method, url, body, headers):
- body = self.fixtures.load('iface_list.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__disk_list(self, method, url, body, headers):
- body = self.fixtures.load('disk_list.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_iface_attach(self, method, url, body, headers):
- body = self.fixtures.load('iface_attach.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_iface_detach(self, method, url, body, headers):
- body = self.fixtures.load('iface_detach.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_disk_attach(self, method, url, body, headers):
- body = self.fixtures.load('disk_attach.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__vm_disk_detach(self, method, url, body, headers):
- body = self.fixtures.load('disk_detach.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__disk_create(self, method, url, body, headers):
- body = self.fixtures.load('disk_create.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__disk_create_from(self, method, url, body, headers):
- body = self.fixtures.load('disk_create_from.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__disk_info(self, method, url, body, headers):
- body = self.fixtures.load('disk_info.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__disk_update(self, method, url, body, headers):
- body = self.fixtures.load('disk_update.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__disk_delete(self, method, url, body, headers):
- body = self.fixtures.load('disk_delete.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-
-class DummyTransport(MockGandiTransport):
- mockCls = GandiMockHttp
-
-
-class GandiTests(BaseGandiTests):
-
- driverCls = GandiNodeDriver
- transportCls = DummyTransport
- params = GANDI_PARAMS
+class GandiTests(unittest.TestCase):
node_name = 'test2'
+ def setUp(self):
+ GandiNodeDriver.connectionCls.conn_classes = (
+ GandiMockHttp, GandiMockHttp)
+ GandiMockHttp.type = None
+ self.driver = GandiNodeDriver(*GANDI_PARAMS)
+
def test_list_nodes(self):
nodes = self.driver.list_nodes()
self.assertTrue(len(nodes) > 0)
@@ -254,5 +155,98 @@ class GandiTests(BaseGandiTests):
self.assertTrue(self.driver.ex_update_disk(disks[0], new_size=4096))
+class GandiMockHttp(BaseGandiMockHttp):
+
+ fixtures = ComputeFileFixtures('gandi')
+
+ def _xmlrpc__datacenter_list(self, method, url, body, headers):
+ body = self.fixtures.load('datacenter_list.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__image_list(self, method, url, body, headers):
+ body = self.fixtures.load('image_list_dc0.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_list(self, method, url, body, headers):
+ body = self.fixtures.load('vm_list.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__ip_list(self, method, url, body, headers):
+ body = self.fixtures.load('ip_list.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__account_info(self, method, url, body, headers):
+ body = self.fixtures.load('account_info.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_info(self, method, url, body, headers):
+ body = self.fixtures.load('vm_info.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_delete(self, method, url, body, headers):
+ body = self.fixtures.load('vm_delete.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__operation_info(self, method, url, body, headers):
+ body = self.fixtures.load('operation_info.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_create_from(self, method, url, body, headers):
+ body = self.fixtures.load('vm_create_from.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_reboot(self, method, url, body, headers):
+ body = self.fixtures.load('vm_reboot.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_stop(self, method, url, body, headers):
+ body = self.fixtures.load('vm_stop.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__iface_list(self, method, url, body, headers):
+ body = self.fixtures.load('iface_list.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__disk_list(self, method, url, body, headers):
+ body = self.fixtures.load('disk_list.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_iface_attach(self, method, url, body, headers):
+ body = self.fixtures.load('iface_attach.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_iface_detach(self, method, url, body, headers):
+ body = self.fixtures.load('iface_detach.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_disk_attach(self, method, url, body, headers):
+ body = self.fixtures.load('disk_attach.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__vm_disk_detach(self, method, url, body, headers):
+ body = self.fixtures.load('disk_detach.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__disk_create(self, method, url, body, headers):
+ body = self.fixtures.load('disk_create.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__disk_create_from(self, method, url, body, headers):
+ body = self.fixtures.load('disk_create_from.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__disk_info(self, method, url, body, headers):
+ body = self.fixtures.load('disk_info.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__disk_update(self, method, url, body, headers):
+ body = self.fixtures.load('disk_update.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__disk_delete(self, method, url, body, headers):
+ body = self.fixtures.load('disk_delete.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+
if __name__ == '__main__':
sys.exit(unittest.main())
Added: libcloud/trunk/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml?rev=1441956&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml (added)
+++ libcloud/trunk/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml Sun Feb 3 19:24:19 2013
@@ -0,0 +1,17 @@
+<?xml version='1.0'?>
+<methodResponse>
+ <fault>
+ <value>
+ <struct>
+ <member>
+ <name>faultCode</name>
+ <value><int>581042</int></value>
+ </member>
+ <member>
+ <name>faultString</name>
+ <value><string>Zone does not exist</string></value>
+ </member>
+ </struct>
+ </value>
+ </fault>
+</methodResponse>
Modified: libcloud/trunk/libcloud/test/dns/test_gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/test_gandi.py?rev=1441956&r1=1441955&r2=1441956&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/dns/test_gandi.py (original)
+++ libcloud/trunk/libcloud/test/dns/test_gandi.py Sun Feb 3 19:24:19 2013
@@ -17,106 +17,21 @@ import sys
import unittest
from libcloud.utils.py3 import httplib
-from libcloud.utils.py3 import xmlrpclib
from libcloud.dns.types import RecordType, ZoneDoesNotExistError
from libcloud.dns.types import RecordDoesNotExistError
from libcloud.dns.drivers.gandi import GandiDNSDriver
-from libcloud.test import MockHttp
from libcloud.test.file_fixtures import DNSFileFixtures
from libcloud.test.secrets import DNS_GANDI
-from libcloud.test.common.test_gandi import MockGandiTransport, BaseGandiTests
+from libcloud.test.common.test_gandi import BaseGandiMockHttp
-Fault = xmlrpclib.Fault
-class GandiMockHttp(MockHttp):
- fixtures = DNSFileFixtures('gandi')
-
- def _xmlrpc__domain_zone_create(self, method, url, body, headers):
- body = self.fixtures.load('create_zone.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__domain_zone_update(self, method, url, body, headers):
- body = self.fixtures.load('get_zone.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__domain_zone_list(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_list(self, method, url, body, headers):
- body = self.fixtures.load('list_records.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__domain_zone_record_add(self, method, url, body, headers):
- body = self.fixtures.load('create_record.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__domain_zone_delete(self, method, url, body, headers):
- body = self.fixtures.load('delete_zone.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__domain_zone_info(self, method, url, body, headers):
- body = self.fixtures.load('get_zone.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__domain_zone_record_delete(self, method, url, body, headers):
- body = self.fixtures.load('delete_record.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__domain_zone_record_update(self, method, url, body, headers):
- body = self.fixtures.load('create_record.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _xmlrpc__domain_zone_version_new(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(self, method, url, body, headers):
- 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):
- raise Fault(581042, "Zone does not exist")
-
- def _xmlrpc__domain_zone_info_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
- raise Fault(581042, "Zone does not exist")
+class GandiTests(unittest.TestCase):
- def _xmlrpc__domain_zone_list_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
- raise Fault(581042, "Zone does not exist")
-
- def _xmlrpc__domain_zone_delete_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
- raise Fault(581042, "Zone does not exist")
-
- 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):
- 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):
- 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):
- 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):
- body = self.fixtures.load('new_version.xml')
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-
-class DummyTransport(MockGandiTransport):
- mockCls = GandiMockHttp
-
-
-class GandiTests(BaseGandiTests):
-
- driverCls = GandiDNSDriver
- transportCls = DummyTransport
- params = DNS_GANDI
+ def setUp(self):
+ GandiDNSDriver.connectionCls.conn_classes = (
+ GandiMockHttp, GandiMockHttp)
+ GandiMockHttp.type = None
+ self.driver = GandiDNSDriver(*DNS_GANDI)
def test_list_record_types(self):
record_types = self.driver.list_record_types()
@@ -285,5 +200,88 @@ class GandiTests(BaseGandiTests):
self.fail('Exception was not thrown')
+class GandiMockHttp(BaseGandiMockHttp):
+ fixtures = DNSFileFixtures('gandi')
+
+ def _xmlrpc__domain_zone_create(self, method, url, body, headers):
+ body = self.fixtures.load('create_zone.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__domain_zone_update(self, method, url, body, headers):
+ body = self.fixtures.load('get_zone.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__domain_zone_list(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_list(self, method, url, body, headers):
+ body = self.fixtures.load('list_records.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__domain_zone_record_add(self, method, url, body, headers):
+ body = self.fixtures.load('create_record.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__domain_zone_delete(self, method, url, body, headers):
+ body = self.fixtures.load('delete_zone.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__domain_zone_info(self, method, url, body, headers):
+ body = self.fixtures.load('get_zone.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__domain_zone_record_delete(self, method, url, body, headers):
+ body = self.fixtures.load('delete_record.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__domain_zone_record_update(self, method, url, body, headers):
+ body = self.fixtures.load('create_record.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc__domain_zone_version_new(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(self, method, url, body, headers):
+ 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):
+ 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):
+ 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):
+ 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):
+ 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):
+ 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):
+ 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):
+ 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):
+ 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):
+ body = self.fixtures.load('new_version.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
if __name__ == '__main__':
sys.exit(unittest.main())