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 2011/10/08 12:19:39 UTC
svn commit: r1180349 - /libcloud/trunk/libcloud/dns/drivers/zerigo.py
Author: tomaz
Date: Sat Oct 8 10:19:38 2011
New Revision: 1180349
URL: http://svn.apache.org/viewvc?rev=1180349&view=rev
Log:
More progress on Zerigo DNS driver.
Modified:
libcloud/trunk/libcloud/dns/drivers/zerigo.py
Modified: libcloud/trunk/libcloud/dns/drivers/zerigo.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/zerigo.py?rev=1180349&r1=1180348&r2=1180349&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/zerigo.py (original)
+++ libcloud/trunk/libcloud/dns/drivers/zerigo.py Sat Oct 8 10:19:38 2011
@@ -24,7 +24,7 @@ from xml.etree import ElementTree as ET
from libcloud.utils import fixxpath, findtext, findattr, findall
from libcloud.common.base import Response, ConnectionUserAndKey
-from libcloud.common.types import InvalidCredsError
+from libcloud.common.types import InvalidCredsError, LibcloudError
from libcloud.dns.types import Provider, RecordType
from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
from libcloud.dns.base import DNSDriver, Zone, Record
@@ -47,11 +47,20 @@ class ZerigoDNSResponse(Response):
return body
def parse_error(self):
- if int(self.status) == 401:
+ status = int(self.status)
+
+ if status == 401:
if not self.body:
raise InvalidCredsError(str(self.status) + ': ' + self.error)
else:
raise InvalidCredsError(self.body)
+ elif status == 404:
+ context = self.connection.context
+ if context['resource'] == 'zone':
+ raise ZoneDoesNotExistError(value='', driver=self,
+ zone_id=context['id'])
+
+ return self.body
class ZerigoDNSConnection(ConnectionUserAndKey):
@@ -64,6 +73,21 @@ class ZerigoDNSConnection(ConnectionUser
headers['Authorization'] = 'Basic %s' % (auth_b64)
return headers
+ def request(self, action, params=None, data='', headers=None,
+ method='GET'):
+ if not headers:
+ headers = {}
+ if not params:
+ params = {}
+
+ if method in ("POST", "PUT"):
+ headers = {'Content-Type': 'application/xml; charset=UTF-8'}
+ return super(ZerigoDNSConnection, self).request(action=action,
+ params=params,
+ data=data,
+ method=method,
+ headers=headers)
+
class ZerigoDNSDriver(DNSDriver):
type = Provider.ZERIGO
@@ -75,11 +99,82 @@ class ZerigoDNSDriver(DNSDriver):
path = API_ROOT + 'zones.xml'
data = self.connection.request(path).object
zones = self._to_zones(elem=data)
+ return zones
- if len(zones) == 0:
- return []
+ def list_records(self, zone):
+ # TODO: Use LazyList
+ path = API_ROOT + 'zones/%s/hosts.xml' % (zone.id)
+ self.connection.set_context({'resource': 'zone', 'id': zone.id})
+ data = self.connection.request(path).object
+ records = self._to_records(elem=data, zone=zone)
+ return records
- return zones[0]
+ def get_zone(self, zone_id):
+ path = API_ROOT + 'zones/%s.xml' % (zone_id)
+ self.connection.set_context({'resource': 'zone', 'id': zone_id})
+ data = self.connection.request(path).object
+ zone = self._to_zone(elem=data)
+ return zone
+
+ def get_record(self, zone_id, record_id):
+ zone = self.get_zone(zone_id=zone_id)
+ path = API_ROOT + 'hosts/%s.xml' % (record_id)
+ data = self.connection.request(path).object
+ record = self._to_record(elem=data, zone=zone)
+ return record
+
+ def create_zone(self, domain, type='master', ttl=None, extra=None):
+ """
+ Create a new zone.
+
+ Provider API docs:
+ https://www.zerigo.com/docs/apis/dns/1.1/zones/create
+ """
+ path = API_ROOT + 'zones.xml'
+
+ zone_elem = ET.Element('zone', {})
+ domain_elem = ET.SubElement(zone_elem, 'domain')
+ domain_elem.text = domain
+ ns_type_elem = ET.SubElement(zone_elem, 'ns-type')
+
+ if type == 'master':
+ ns_type_elem.text = 'pri_sec'
+ elif type == 'slave':
+ if not extra or 'ns1' not in extra:
+ raise LibcloudError('ns1 extra attribute is required when ' +
+ 'zone type is slave', driver=self)
+
+ ns_type_elem.text = 'sec'
+ ns1_elem = ET.SubElement(zone_elem, 'ns1')
+ ns1_elem.text = extra['ns1']
+ elif type == 'std_master':
+ # TODO: Each driver should provide supported zone types
+ # Slave name servers are elsewhere
+ if not extra or 'slave-nameservers' not in extra:
+ raise LibcloudError('slave-nameservers extra attribute is ' +
+ 'required whenzone type is std_master',
+ driver=self)
+
+ ns_type_elem.text = 'pri'
+ slave_nameservers_elem = ET.SubElement(zone_elem,
+ 'slave-nameservers')
+ slave_nameservers_elem.text = extra['slave-nameservers']
+
+ if ttl:
+ default_ttl_elem = ET.SubElement(zone_elem, 'default-ttl')
+ default_ttl_elem.text = str(ttl)
+
+ if extra and 'tag-list' in extra:
+ tags = extra['tag-list']
+
+ tags_elem = ET.SubElement(zone_elem, 'tag-list')
+ tags_elem.text = ' '.join(tags)
+
+ data = self.connection.request(action=path,
+ data=ET.tostring(zone_elem),
+ method='POST').object
+ zone = self._to_zone(elem=data)
+ return zone
def _to_zones(self, elem):
zones = []
@@ -103,10 +198,41 @@ class ZerigoDNSDriver(DNSDriver):
notes = findtext(element=elem, xpath='notes')
nx_ttl = findtext(element=elem, xpath='nx-ttl')
slave_nameservers = findtext(element=elem, xpath='slave-nameservers')
+ tags = findtext(element=elem, xpath='tag-list')
+ tags = tags.split(' ') if tags else []
extra = {'hostmaster': hostmaster, 'custom-ns': custom_ns,
'custom-nameservers': custom_nameservers, 'notes': notes,
- 'nx-ttl': nx_ttl, 'slave-nameservers': slave_nameservers}
+ 'nx-ttl': nx_ttl, 'slave-nameservers': slave_nameservers,
+ 'tags': tags}
zone = Zone(id=str(id), domain=domain, type=type, ttl=int(ttl),
- extra=extra, driver=self)
+ driver=self, extra=extra)
return zone
+
+ def _to_records(self, elem, zone):
+ records = []
+
+ for item in findall(element=elem, xpath='host'):
+ record = self._to_record(elem=item, zone=zone)
+ records.append(record)
+
+ return records
+
+ def _to_record(self, elem, zone):
+ id = findtext(element=elem, xpath='id')
+ name = findtext(element=elem, xpath='hostname')
+ type = findtext(element=elem, xpath='host-type')
+ type = self._string_to_record_type(type)
+ data = findtext(element=elem, xpath='data')
+
+ notes = findtext(element=elem, xpath='notes')
+ state = findtext(element=elem, xpath='state')
+ fqdn = findtext(element=elem, xpath='fqdn')
+ priority = findtext(element=elem, xpath='priority')
+
+ extra = {'notes': notes, 'state': state, 'fqdn': fqdn,
+ 'priority': priority}
+
+ record = Record(id=id, name=name, type=type, data=data,
+ zone=zone, driver=self, extra=extra)
+ return record