You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2012/12/13 04:52:46 UTC
svn commit: r1421073 - in /libcloud/trunk: ./ libcloud/common/
libcloud/compute/drivers/ libcloud/dns/ libcloud/dns/drivers/
libcloud/test/ libcloud/test/compute/ libcloud/test/dns/
libcloud/test/dns/fixtures/hostvirtual/
Author: tomaz
Date: Thu Dec 13 03:52:44 2012
New Revision: 1421073
URL: http://svn.apache.org/viewvc?rev=1421073&view=rev
Log:
New driver for HostVirtual provider (www.vr.org).
Contributed by Dinesh Bhoopathy, part of LIBCLOUD-249.
Added:
libcloud/trunk/libcloud/common/hostvirtual.py
libcloud/trunk/libcloud/dns/drivers/hostvirtual.py
libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/
libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_record.json
libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_zone.json
libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_records.json
libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_zones.json
libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json
libcloud/trunk/libcloud/test/dns/test_hostvirtual.py
Modified:
libcloud/trunk/CHANGES
libcloud/trunk/libcloud/compute/drivers/hostvirtual.py
libcloud/trunk/libcloud/dns/providers.py
libcloud/trunk/libcloud/dns/types.py
libcloud/trunk/libcloud/test/compute/test_hostvirtual.py
libcloud/trunk/libcloud/test/secrets.py-dist
Modified: libcloud/trunk/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1421073&r1=1421072&r2=1421073&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Thu Dec 13 03:52:44 2012
@@ -101,6 +101,9 @@ Changes with Apache Libcloud in developm
(LIBCLOUD-247)
[Tomaz Muraus]
+ - New driver for HostVirtual provider (www.vr.org).
+ [Dinesh Bhoopathy]
+
Changes with Apache Libcloud 0.11.3:
*) Storage
Added: libcloud/trunk/libcloud/common/hostvirtual.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/hostvirtual.py?rev=1421073&view=auto
==============================================================================
--- libcloud/trunk/libcloud/common/hostvirtual.py (added)
+++ libcloud/trunk/libcloud/common/hostvirtual.py Thu Dec 13 03:52:44 2012
@@ -0,0 +1,77 @@
+# 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.
+
+try:
+ import simplejson as json
+except ImportError:
+ import json
+
+from libcloud.utils.py3 import httplib
+from libcloud.common.base import ConnectionKey, JsonResponse
+from libcloud.common.types import LibcloudError
+
+API_HOST = 'www.vr.org'
+
+
+class HostVirtualException(LibcloudError):
+ def __init__(self, code, message):
+ self.code = code
+ self.message = message
+ self.args = (code, message)
+
+ def __str__(self):
+ return self.__repr__()
+
+ def __repr__(self):
+ return '<HostVirtualException in %d: %s>' % (self.code, self.message)
+
+
+class HostVirtualConnection(ConnectionKey):
+ host = API_HOST
+
+ def add_default_params(self, params):
+ params['key'] = self.key
+ return params
+
+
+class HostVirtualResponse(JsonResponse):
+ valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
+ httplib.NO_CONTENT]
+
+ def parse_body(self):
+ if not self.body:
+ return None
+
+ data = json.loads(self.body)
+ return data
+
+ def parse_error(self):
+ context = self.connection.context
+ data = self.parse_body()
+ status = int(self.status)
+
+ if self.status == httplib.UNAUTHORIZED:
+ raise InvalidCredsError(
+ data['error']['code'] + ': ' + data['error']['message'])
+ elif self.status == httplib.PRECONDITION_FAILED:
+ raise HostVirtualException(
+ data['error']['code'], data['error']['message'])
+ elif self.status == httplib.NOT_FOUND:
+ raise HostVirtualException(
+ data['error']['code'], data['error']['message'])
+
+ return self.body
+
+ def success(self):
+ return self.status in self.valid_response_codes
Modified: libcloud/trunk/libcloud/compute/drivers/hostvirtual.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/hostvirtual.py?rev=1421073&r1=1421072&r2=1421073&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/hostvirtual.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/hostvirtual.py Thu Dec 13 03:52:44 2012
@@ -3,9 +3,8 @@
# 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
+# 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,
@@ -26,15 +25,15 @@ except ImportError:
from libcloud.utils.py3 import httplib
-from libcloud.common.types import LibcloudError
+from libcloud.common.hostvirtual import HostVirtualResponse
+from libcloud.common.hostvirtual import HostVirtualConnection
+from libcloud.common.hostvirtual import HostVirtualException
from libcloud.compute.providers import Provider
-from libcloud.common.base import ConnectionKey, JsonResponse
from libcloud.compute.types import NodeState, InvalidCredsError
from libcloud.compute.base import Node, NodeDriver
from libcloud.compute.base import NodeImage, NodeSize, NodeLocation
from libcloud.compute.base import NodeAuthSSHKey, NodeAuthPassword
-API_HOST = 'www.vr.org'
API_ROOT = '/vapi'
#API_VERSION = '0.1'
@@ -49,64 +48,19 @@ NODE_STATE_MAP = {
}
-class HostVirtualException(LibcloudError):
- def __init__(self, code, message):
- self.code = code
- self.message = message
- self.args = (code, message)
-
- def __str__(self):
- return self.__repr__()
-
- def __repr__(self):
- return "<HostVirtualException in %d : %s>" % (self.code, self.message)
-
-
-class HostVirtualResponse(JsonResponse):
- valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
- httplib.NO_CONTENT]
-
- def parse_body(self):
- if not self.body:
- return None
-
- data = json.loads(self.body)
- return data
-
- def parse_error(self):
- if self.status == 401:
- data = self.parse_body()
- raise InvalidCredsError(
- data['error']['code'] + ': ' + data['error']['message'])
- elif self.status == 412:
- data = self.parse_body()
- raise HostVirtualException(
- data['error']['code'], data['error']['message'])
- elif self.status == 404:
- data = self.parse_body()
- raise HostVirtualException(
- data['error']['code'], data['error']['message'])
- else:
- return self.body
-
- def success(self):
- return self.status in self.valid_response_codes
-
+class HostVirtualComputeResponse(HostVirtualResponse):
+ pass
-class HostVirtualConnection(ConnectionKey):
- host = API_HOST
- responseCls = HostVirtualResponse
- def add_default_params(self, params):
- params["key"] = self.key
- return params
+class HostVirtualComputeConnection(HostVirtualConnection):
+ responseCls = HostVirtualComputeResponse
class HostVirtualNodeDriver(NodeDriver):
type = Provider.HOSTVIRTUAL
name = 'HostVirtual'
website = 'http://www.vr.org'
- connectionCls = HostVirtualConnection
+ connectionCls = HostVirtualComputeConnection
def __init__(self, key):
self.location = None
Added: libcloud/trunk/libcloud/dns/drivers/hostvirtual.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/hostvirtual.py?rev=1421073&view=auto
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/hostvirtual.py (added)
+++ libcloud/trunk/libcloud/dns/drivers/hostvirtual.py Thu Dec 13 03:52:44 2012
@@ -0,0 +1,241 @@
+# 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.
+
+__all__ = [
+ 'HostVirtualDNSDriver'
+]
+
+from libcloud.utils.py3 import httplib
+from libcloud.utils.misc import merge_valid_keys, get_new_obj
+from libcloud.common.hostvirtual import HostVirtualResponse
+from libcloud.common.hostvirtual import HostVirtualConnection
+from libcloud.compute.drivers.hostvirtual import API_ROOT
+from libcloud.compute.drivers.hostvirtual import HostVirtualConnection
+from libcloud.compute.drivers.hostvirtual import HostVirtualResponse
+from libcloud.dns.types import Provider, RecordType
+from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
+from libcloud.dns.base import DNSDriver, Zone, Record
+
+try:
+ import simplejson as json
+except:
+ import json
+
+VALID_RECORD_EXTRA_PARAMS = ['prio', 'ttl']
+
+
+class HostVirtualDNSResponse(HostVirtualResponse):
+ def parse_error(self):
+ context = self.connection.context
+ status = int(self.status)
+
+ if status == httplib.NOT_FOUND:
+ if context['resource'] == 'zone':
+ raise ZoneDoesNotExistError(value='', driver=self,
+ zone_id=context['id'])
+ elif context['resource'] == 'record':
+ raise RecordDoesNotExistError(value='', driver=self,
+ record_id=context['id'])
+
+ super(HostVirtualDNSResponse, self).parse_error()
+ return self.body
+
+
+class HostVirtualDNSConnection(HostVirtualConnection):
+ responseCls = HostVirtualDNSResponse
+
+
+class HostVirtualDNSDriver(DNSDriver):
+ type = Provider.HOSTVIRTUAL
+ name = 'Host Virtual DNS'
+ website = 'http://www.vr.org/'
+ connectionCls = HostVirtualDNSConnection
+
+ RECORD_TYPE_MAP = {
+ RecordType.A: 'A',
+ RecordType.AAAA: 'AAAA',
+ RecordType.CNAME: 'CNAME',
+ RecordType.MX: 'MX',
+ RecordType.TXT: 'TXT',
+ RecordType.NS: 'SPF',
+ RecordType.SRV: 'SRV',
+ }
+
+ def _to_zones(self, items):
+ zones = []
+ for item in items:
+ zones.append(self._to_zone(item))
+ return zones
+
+ def _to_zone(self, item):
+ extra = {}
+ if 'records' in item:
+ extra['records'] = item['records']
+ if item['type'] == 'NATIVE':
+ item['type'] = 'master'
+ zone = Zone(id=item['id'], domain=item['name'],
+ type=item['type'], ttl=item['ttl'],
+ driver=self, extra=extra)
+ return zone
+
+ def _to_records(self, items, zone=None):
+ records = []
+
+ for item in items:
+ records.append(self._to_record(item=item, zone=zone))
+ return records
+
+ def _to_record(self, item, zone=None):
+ extra = {'ttl': item['ttl']}
+ type = self._string_to_record_type(item['type'])
+ record = Record(id=item['id'], name=item['name'],
+ type=type, data=item['content'],
+ zone=zone, driver=self, extra=extra)
+ return record
+
+ def list_zones(self):
+ result = self.connection.request(
+ API_ROOT + '/dns/zones/').object
+ zones = self._to_zones(result)
+ return zones
+
+ def list_records(self, zone):
+ params = {'zone_id': zone.id}
+ self.connection.set_context({'resource': 'zone', 'id': zone.id})
+ result = self.connection.request(
+ API_ROOT + '/dns/records/', data=json.dumps(params)).object
+ records = self._to_records(items=result, zone=zone)
+ return records
+
+ def get_zone(self, zone_id):
+ params = {'id': zone_id}
+ self.connection.set_context({'resource': 'zone', 'id': zone_id})
+ result = self.connection.request(
+ API_ROOT + '/dns/zone/', params=params).object
+ if 'id' not in result:
+ raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone_id)
+ zone = self._to_zone(result)
+ return zone
+
+ def get_record(self, zone_id, record_id):
+ zone = self.get_zone(zone_id=zone_id)
+ params = {'id': record_id}
+ self.connection.set_context({'resource': 'record', 'id': record_id})
+ result = self.connection.request(
+ API_ROOT + '/dns/record/', params=params).object
+ if 'id' not in result:
+ raise RecordDoesNotExistError(value='',
+ driver=self, record_id=record_id)
+ record = self._to_record(item=result, zone=zone)
+ return record
+
+ def delete_zone(self, zone):
+ params = {'zone_id': zone.id}
+ self.connection.set_context({'resource': 'zone', 'id': zone.id})
+ result = self.connection.request(
+ API_ROOT + '/dns/zone/', params=params, method='DELETE').object
+ return bool(result)
+
+ def delete_record(self, record):
+ params = {'id': record.id}
+ self.connection.set_context({'resource': 'record', 'id': record.id})
+ result = self.connection.request(
+ API_ROOT + '/dns/record/', params=params, method='DELETE').object
+
+ return bool(result)
+
+ def create_zone(self, domain, type='NATIVE', ttl=None, extra=None):
+ if type == 'master':
+ type = 'NATIVE'
+ elif type == 'slave':
+ type = 'SLAVE'
+ params = {'name': domain, 'type': type, 'ttl': ttl}
+ result = self.connection.request(
+ API_ROOT + '/dns/zone/',
+ data=json.dumps(params), method='POST').object
+ extra = {
+ 'soa': result['soa'],
+ 'ns': result['ns']
+ }
+ zone = Zone(id=result['id'], domain=domain,
+ type=type, ttl=ttl, extra=extra, driver=self)
+ return zone
+
+ def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None):
+ params = {'id': zone.id}
+ if domain:
+ params['name'] = domain
+ if type:
+ params['type'] = type
+ self.connection.set_context({'resource': 'zone', 'id': zone.id})
+ self.connection.request(API_ROOT + '/dns/zone/',
+ data=json.dumps(params), method='PUT').object
+ updated_zone = get_new_obj(
+ obj=zone, klass=Zone,
+ attributes={
+ 'domain': domain,
+ 'type': type,
+ 'ttl': ttl,
+ 'extra': extra
+ })
+ return updated_zone
+
+ def create_record(self, name, zone, type, data, extra=None):
+ params = {
+ 'name': name,
+ 'type': self.RECORD_TYPE_MAP[type],
+ 'domain_id': zone.id,
+ 'content': data
+ }
+ merged = merge_valid_keys(
+ params=params,
+ valid_keys=VALID_RECORD_EXTRA_PARAMS,
+ extra=extra
+ )
+ self.connection.set_context({'resource': 'zone', 'id': zone.id})
+ result = self.connection.request(
+ API_ROOT + '/dns/record/',
+ data=json.dumps(params), method='POST').object
+ record = Record(id=result['id'], name=name,
+ type=type, data=data,
+ extra=merged, zone=zone, driver=self)
+ return record
+
+ def update_record(self, record, name=None, type=None,
+ data=None, extra=None):
+ params = {
+ 'domain_id': record.zone.id,
+ 'record_id': record.id
+ }
+ if name:
+ params['name'] = name
+ if data:
+ params['content'] = data
+ if type is not None:
+ params['type'] = self.RECORD_TYPE_MAP[type]
+ merged = merge_valid_keys(
+ params=params,
+ valid_keys=VALID_RECORD_EXTRA_PARAMS,
+ extra=extra
+ )
+ self.connection.set_context({'resource': 'record', 'id': record.id})
+ self.connection.request(API_ROOT + '/dns/record/',
+ data=json.dumps(params), method='PUT').object
+ updated_record = get_new_obj(
+ obj=record, klass=Record, attributes={
+ 'name': name, 'data': data,
+ 'type': type,
+ 'extra': merged
+ })
+ return updated_record
Modified: libcloud/trunk/libcloud/dns/providers.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/providers.py?rev=1421073&r1=1421072&r2=1421073&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/providers.py (original)
+++ libcloud/trunk/libcloud/dns/providers.py Thu Dec 13 03:52:44 2012
@@ -27,7 +27,9 @@ DRIVERS = {
Provider.RACKSPACE_US:
('libcloud.dns.drivers.rackspace', 'RackspaceUSDNSDriver'),
Provider.RACKSPACE_UK:
- ('libcloud.dns.drivers.rackspace', 'RackspaceUKDNSDriver')
+ ('libcloud.dns.drivers.rackspace', 'RackspaceUKDNSDriver'),
+ Provider.HOSTVIRTUAL:
+ ('libcloud.dns.drivers.hostvirtual', 'HostVirtualDNSDriver'),
}
Modified: libcloud/trunk/libcloud/dns/types.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/types.py?rev=1421073&r1=1421072&r2=1421073&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/types.py (original)
+++ libcloud/trunk/libcloud/dns/types.py Thu Dec 13 03:52:44 2012
@@ -34,6 +34,7 @@ class Provider(object):
RACKSPACE_US = 'rackspace_us'
RACKSPACE_UK = 'rackspace_uk'
ROUTE53 = 'route53'
+ HOSTVIRTUAL = 'hostvirtual'
class RecordType(object):
Modified: libcloud/trunk/libcloud/test/compute/test_hostvirtual.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_hostvirtual.py?rev=1421073&r1=1421072&r2=1421073&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_hostvirtual.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_hostvirtual.py Thu Dec 13 03:52:44 2012
@@ -15,11 +15,6 @@
import sys
import unittest
-try:
- import simplejson as json
-except ImportError:
- import json
-
from libcloud.utils.py3 import httplib
from libcloud.compute.drivers.hostvirtual import HostVirtualNodeDriver
@@ -79,7 +74,7 @@ class HostVirtualTest(unittest.TestCase)
node = self.driver.list_nodes()[0]
self.assertTrue(self.driver.ex_stop_node(node))
- def test_start_node_response(self):
+ def test_start_node(self):
node = self.driver.list_nodes()[0]
self.assertTrue(self.driver.ex_start_node(node))
Added: libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_record.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_record.json?rev=1421073&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_record.json (added)
+++ libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_record.json Thu Dec 13 03:52:44 2012
@@ -0,0 +1,8 @@
+{
+ "id": "300377",
+ "name": "*.t.com",
+ "type": "CNAME",
+ "content": "t.com",
+ "ttl": "86400",
+ "prio": null
+}
Added: libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_zone.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_zone.json?rev=1421073&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_zone.json (added)
+++ libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/get_zone.json Thu Dec 13 03:52:44 2012
@@ -0,0 +1,47 @@
+{
+ "id": "47234",
+ "name": "t.com",
+ "type": "NATIVE",
+ "ttl": "3600",
+ "soa": {
+ "primary": "ns1.hostvirtual.com",
+ "hostmaster": "support@HOSTVIRTUAL.COM",
+ "serial": "2012100901",
+ "refresh": "10800",
+ "retry": "3600",
+ "expire": "604800",
+ "default_ttl": "3600"
+ },
+ "ns": [
+ "ns4.hostvirtual.com",
+ "ns3.hostvirtual.com",
+ "ns2.hostvirtual.com",
+ "ns1.hostvirtual.com"
+ ],
+ "records": [
+ {
+ "id": "300377",
+ "name": "*.t.com",
+ "type": "CNAME",
+ "content": "t.com",
+ "ttl": "86400",
+ "prio": null
+ },
+ {
+ "id": "300719",
+ "name": "blah.com.",
+ "type": "A",
+ "content": "0.0.0.0",
+ "ttl": null,
+ "prio": null
+ },
+ {
+ "id": "300728",
+ "name": "blahblah.com.t.com",
+ "type": "A",
+ "content": "1.1.1.1",
+ "ttl": null,
+ "prio": "10"
+ }
+ ]
+}
Added: libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_records.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_records.json?rev=1421073&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_records.json (added)
+++ libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_records.json Thu Dec 13 03:52:44 2012
@@ -0,0 +1,26 @@
+[
+ {
+ "id": "300377",
+ "name": "*.t.com",
+ "type": "CNAME",
+ "content": "t.com",
+ "ttl": "86400",
+ "prio": null
+ },
+ {
+ "id": "300719",
+ "name": "www.t.com",
+ "type": "A",
+ "content": "208.111.35.173",
+ "ttl": null,
+ "prio": null
+ },
+ {
+ "id": "300728",
+ "name": "blahblah.t.com",
+ "type": "A",
+ "content": "208.111.35.173",
+ "ttl": null,
+ "prio": "10"
+ }
+]
Added: libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_zones.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_zones.json?rev=1421073&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_zones.json (added)
+++ libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/list_zones.json Thu Dec 13 03:52:44 2012
@@ -0,0 +1,32 @@
+[
+ {
+ "id": "47234",
+ "name": "t.com",
+ "type": "NATIVE",
+ "ttl": "3600"
+ },
+ {
+ "id": "48170",
+ "name": "newbug.net",
+ "type": "NATIVE",
+ "ttl": "3600"
+ },
+ {
+ "id": "48017",
+ "name": "newblah.com",
+ "type": "NATIVE",
+ "ttl": "3600"
+ },
+ {
+ "id": "47288",
+ "name": "fromapi.com",
+ "type": "NATIVE",
+ "ttl": "3600"
+ },
+ {
+ "id": "48008",
+ "name": "blahnew.com",
+ "type": "NATIVE",
+ "ttl": "3600"
+ }
+]
Added: libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json?rev=1421073&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json (added)
+++ libcloud/trunk/libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json Thu Dec 13 03:52:44 2012
@@ -0,0 +1,6 @@
+{
+ "error": {
+ "code": 404,
+ "message": "Not Found: id, validate_dns_zone_owner"
+ }
+}
Added: libcloud/trunk/libcloud/test/dns/test_hostvirtual.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/dns/test_hostvirtual.py?rev=1421073&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/dns/test_hostvirtual.py (added)
+++ libcloud/trunk/libcloud/test/dns/test_hostvirtual.py Thu Dec 13 03:52:44 2012
@@ -0,0 +1,258 @@
+# 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.
+
+import sys
+import unittest
+
+from libcloud.utils.py3 import httplib
+
+from libcloud.dns.types import RecordType, ZoneDoesNotExistError
+from libcloud.dns.types import RecordDoesNotExistError
+from libcloud.dns.drivers.hostvirtual import HostVirtualDNSDriver
+from libcloud.test import MockHttp
+from libcloud.test.file_fixtures import DNSFileFixtures
+from libcloud.test.secrets import DNS_PARAMS_HOSTVIRTUAL
+
+
+class HostVirtualTests(unittest.TestCase):
+ def setUp(self):
+ HostVirtualDNSDriver.connectionCls.conn_classes = (
+ None, HostVirtualMockHttp)
+ HostVirtualMockHttp.type = None
+ self.driver = HostVirtualDNSDriver(*DNS_PARAMS_HOSTVIRTUAL)
+
+ def test_list_record_types(self):
+ record_types = self.driver.list_record_types()
+ self.assertEqual(len(record_types), 7)
+ self.assertTrue(RecordType.A in record_types)
+
+ def test_list_zones(self):
+ zones = self.driver.list_zones()
+ self.assertEqual(len(zones), 5)
+
+ zone = zones[0]
+ self.assertEqual(zone.id, '47234')
+ self.assertEqual(zone.type, 'master')
+ self.assertEqual(zone.domain, 't.com')
+ self.assertEqual(zone.ttl, '3600')
+
+ def test_list_records(self):
+ zone = self.driver.list_zones()[0]
+ records = self.driver.list_records(zone=zone)
+ self.assertEqual(len(records), 3)
+
+ record = records[1]
+ self.assertEqual(record.name, 'www.t.com')
+ self.assertEqual(record.id, '300719')
+ self.assertEqual(record.type, RecordType.A)
+ self.assertEqual(record.data, '208.111.35.173')
+
+ def test_get_zone(self):
+ zone = self.driver.get_zone(zone_id='47234')
+ self.assertEqual(zone.id, '47234')
+ self.assertEqual(zone.type, 'master')
+ self.assertEqual(zone.domain, 't.com')
+ self.assertEqual(zone.ttl, '3600')
+
+ def test_get_record(self):
+ record = self.driver.get_record(zone_id='47234', record_id='300377')
+ self.assertEqual(record.id, '300377')
+ self.assertEqual(record.name, '*.t.com')
+ self.assertEqual(record.type, RecordType.CNAME)
+ self.assertEqual(record.data, 't.com')
+
+ def test_list_records_zone_does_not_exist(self):
+ zone = self.driver.list_zones()[0]
+
+ HostVirtualMockHttp.type = 'ZONE_DOES_NOT_EXIST'
+
+ try:
+ self.driver.list_records(zone=zone)
+ except ZoneDoesNotExistError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.zone_id, zone.id)
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_get_zone_does_not_exist(self):
+ HostVirtualMockHttp.type = 'ZONE_DOES_NOT_EXIST'
+
+ try:
+ self.driver.get_zone(zone_id='4444')
+ except ZoneDoesNotExistError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.zone_id, '4444')
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_get_record_zone_does_not_exist(self):
+ HostVirtualMockHttp.type = 'ZONE_DOES_NOT_EXIST'
+
+ try:
+ self.driver.get_record(zone_id='4444', record_id='28536')
+ except ZoneDoesNotExistError:
+ pass
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_get_record_record_does_not_exist(self):
+ HostVirtualMockHttp.type = 'RECORD_DOES_NOT_EXIST'
+
+ try:
+ self.driver.get_record(zone_id='47234', record_id='4444')
+ except RecordDoesNotExistError:
+ pass
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_create_zone(self):
+ zone = self.driver.create_zone(domain='t.com', type='master',
+ ttl=None, extra=None)
+ self.assertEqual(zone.id, '47234')
+ self.assertEqual(zone.domain, 't.com')
+
+ def test_update_zone(self):
+ zone = self.driver.list_zones()[0]
+ updated_zone = self.driver.update_zone(zone=zone, domain='tt.com')
+
+ self.assertEqual(updated_zone.id, zone.id)
+ self.assertEqual(updated_zone.domain, 'tt.com')
+ self.assertEqual(updated_zone.type, zone.type)
+ self.assertEqual(updated_zone.ttl, '3600')
+
+ def test_create_record(self):
+ zone = self.driver.list_zones()[0]
+ record = self.driver.create_record(
+ name='www', zone=zone,
+ type=RecordType.A, data='127.0.0.1'
+ )
+
+ self.assertEqual(record.id, '300377')
+ self.assertEqual(record.name, 'www')
+ self.assertEqual(record.zone, zone)
+ self.assertEqual(record.type, RecordType.A)
+ self.assertEqual(record.data, '127.0.0.1')
+
+ def test_update_record(self):
+ zone = self.driver.list_zones()[0]
+ record = self.driver.list_records(zone=zone)[1]
+ updated_record = self.driver.update_record(record=record, name='www',
+ type=RecordType.AAAA,
+ data='::1')
+ self.assertEqual(record.data, '208.111.35.173')
+
+ self.assertEqual(updated_record.id, record.id)
+ self.assertEqual(updated_record.name, 'www')
+ self.assertEqual(updated_record.zone, record.zone)
+ self.assertEqual(updated_record.type, RecordType.AAAA)
+ self.assertEqual(updated_record.data, '::1')
+
+ def test_delete_zone(self):
+ zone = self.driver.list_zones()[0]
+ status = self.driver.delete_zone(zone=zone)
+ self.assertTrue(status)
+
+ def test_delete_zone_does_not_exist(self):
+ zone = self.driver.list_zones()[0]
+
+ HostVirtualMockHttp.type = 'ZONE_DOES_NOT_EXIST'
+
+ try:
+ self.driver.delete_zone(zone=zone)
+ except ZoneDoesNotExistError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.zone_id, zone.id)
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_delete_record(self):
+ zone = self.driver.list_zones()[0]
+ record = self.driver.list_records(zone=zone)[0]
+ status = self.driver.delete_record(record=record)
+ self.assertTrue(status)
+
+ def test_delete_record_does_not_exist(self):
+ zone = self.driver.list_zones()[0]
+ record = self.driver.list_records(zone=zone)[0]
+ HostVirtualMockHttp.type = 'RECORD_DOES_NOT_EXIST'
+ try:
+ self.driver.delete_record(record=record)
+ except RecordDoesNotExistError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.record_id, record.id)
+ else:
+ self.fail('Exception was not thrown')
+
+
+class HostVirtualMockHttp(MockHttp):
+ fixtures = DNSFileFixtures('hostvirtual')
+
+ def _vapi_dns_zone(self, method, url, body, headers):
+ body = self.fixtures.load('get_zone.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _vapi_dns_zones(self, method, url, body, headers):
+ body = self.fixtures.load('list_zones.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _vapi_dns_record(self, method, url, body, headers):
+ body = self.fixtures.load('get_record.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _vapi_dns_records(self, method, url, body, headers):
+ body = self.fixtures.load('list_records.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _vapi_dns_zone_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
+ body = self.fixtures.load('zone_does_not_exist.json')
+ return (httplib.NOT_FOUND, body,
+ {}, httplib.responses[httplib.NOT_FOUND])
+
+ def _vapi_dns_zone_RECORD_DOES_NOT_EXIST(self, method, url, body, headers):
+ body = self.fixtures.load('get_zone.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _vapi_dns_zones_ZONE_DOES_NOT_EXIST(self, method, url, body, headers):
+ body = self.fixtures.load('zone_does_not_exist.json')
+ return (httplib.NOT_FOUND, body,
+ {}, httplib.responses[httplib.NOT_FOUND])
+
+ def _vapi_dns_record_ZONE_DOES_NOT_EXIST(self, method,
+ url, body, headers):
+ body = self.fixtures.load('zone_does_not_exist.json')
+ return (httplib.NOT_FOUND, body,
+ {}, httplib.responses[httplib.NOT_FOUND])
+
+ def _vapi_dns_record_RECORD_DOES_NOT_EXIST(self, method,
+ url, body, headers):
+ body = self.fixtures.load('zone_does_not_exist.json')
+ return (httplib.NOT_FOUND, body,
+ {}, httplib.responses[httplib.NOT_FOUND])
+
+ def _vapi_dns_records_ZONE_DOES_NOT_EXIST(self, method,
+ url, body, headers):
+ body = self.fixtures.load('zone_does_not_exist.json')
+ return (httplib.NOT_FOUND, body,
+ {}, httplib.responses[httplib.NOT_FOUND])
+
+ def _vapi_dns_zones_RECORD_DOES_NOT_EXIST(self, method,
+ url, body, headers):
+ body = self.fixtures.load('zone_does_not_exist.json')
+ return (httplib.NOT_FOUND, body,
+ {}, httplib.responses[httplib.NOT_FOUND])
+
+
+if __name__ == '__main__':
+ sys.exit(unittest.main())
Modified: libcloud/trunk/libcloud/test/secrets.py-dist
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/secrets.py-dist?rev=1421073&r1=1421072&r2=1421073&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/secrets.py-dist (original)
+++ libcloud/trunk/libcloud/test/secrets.py-dist Thu Dec 13 03:52:44 2012
@@ -51,3 +51,4 @@ LB_BRIGHTBOX_PARAMS = ('user', 'key')
DNS_PARAMS_LINODE = ('user', 'key')
DNS_PARAMS_ZERIGO = ('email', 'api token')
DNS_PARAMS_RACKSPACE = ('user', 'key')
+DNS_PARAMS_HOSTVIRTUAL = ('key',)