You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2016/11/14 23:50:59 UTC
[12/56] [abbrv] libcloud git commit: Removed sdist
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/nsone.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/nsone.py b/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/nsone.py
deleted file mode 100644
index 06297e6..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/nsone.py
+++ /dev/null
@@ -1,344 +0,0 @@
-import sys
-try:
- import simplejson as json
-except ImportError:
- import json
-
-from libcloud.dns.types import Provider, ZoneDoesNotExistError, \
- ZoneAlreadyExistsError, RecordDoesNotExistError, RecordAlreadyExistsError
-from libcloud.utils.py3 import httplib
-from libcloud.dns.base import DNSDriver, Zone, Record, RecordType
-from libcloud.common.nsone import NsOneConnection, NsOneResponse, \
- NsOneException
-
-__all__ = [
- 'NsOneDNSDriver'
-]
-
-
-class NsOneDNSResponse(NsOneResponse):
- pass
-
-
-class NsOneDNSConnection(NsOneConnection):
- responseCls = NsOneDNSResponse
-
-
-class NsOneDNSDriver(DNSDriver):
- name = 'NS1 DNS'
- website = 'https://ns1.com'
- type = Provider.NSONE
- connectionCls = NsOneDNSConnection
-
- RECORD_TYPE_MAP = {
- RecordType.A: 'A',
- RecordType.AAAA: 'AAAA',
- RecordType.CNAME: 'CNAME',
- RecordType.MX: 'MX',
- RecordType.NS: 'NS',
- RecordType.PTR: 'PTR',
- RecordType.SOA: 'SOA',
- RecordType.SRV: 'SRV',
- RecordType.TXT: 'TXT'
- }
-
- def list_zones(self):
- action = '/v1/zones'
- response = self.connection.request(action=action, method='GET')
- zones = self._to_zones(items=response.parse_body())
-
- return zones
-
- def get_zone(self, zone_id):
- """
- :param zone_id: Zone domain name (e.g. example.com)
- :return: :class:`Zone`
- """
- action = '/v1/zones/%s' % zone_id
- try:
- response = self.connection.request(action=action, method='GET')
- except NsOneException:
- e = sys.exc_info()[1]
- if e.message == 'zone not found':
- raise ZoneDoesNotExistError(value=e.message, driver=self,
- zone_id=zone_id)
- else:
- raise e
- zone = self._to_zone(response.objects[0])
-
- return zone
-
- def create_zone(self, domain, type='master', ttl=None, extra=None):
- """
- :param domain: Zone domain name (e.g. example.com)
- :type domain: ``str``
-
- :param type: Zone type (This is not really used. See API docs for extra
- parameters)
- :type type: ``str``
-
- :param ttl: TTL for new records (This is used through the extra param)
- :type ttl: ``int``
-
- :param extra: Extra attributes that are specific to the driver
- such as ttl.
- :type extra: ``dict``
-
- :rtype: :class:`Zone`
- """
- action = '/v1/zones/%s' % domain
- raw_data = {'zone': domain}
- if extra is not None:
- raw_data.update(extra)
- post_data = json.dumps(raw_data)
- try:
- response = self.connection.request(action=action, method='PUT',
- data=post_data)
- except NsOneException:
- e = sys.exc_info()[1]
- if e.message == 'zone already exists':
- raise ZoneAlreadyExistsError(value=e.message, driver=self,
- zone_id=domain)
- else:
- raise e
-
- zone = self._to_zone(response.objects[0])
-
- return zone
-
- def delete_zone(self, zone):
- """
- :param zone: Zone to be deleted.
- :type zone: :class:`Zone`
-
- :return: Boolean
- """
- action = '/v1/zones/%s' % zone.domain
- """zones_list = self.list_zones()
- if not self.ex_zone_exists(zone_id=zone.id, zones_list=zones_list):
- raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone.id)
- """
- try:
- response = self.connection.request(action=action, method='DELETE')
- except NsOneException:
- e = sys.exc_info()[1]
- if e.message == 'zone not found':
- raise ZoneDoesNotExistError(value=e.message, driver=self,
- zone_id=zone.id)
- else:
- raise e
-
- return response.status == httplib.OK
-
- def list_records(self, zone):
- """
- :param zone: Zone to list records for.
- :type zone: :class:`Zone`
-
- :return: ``list`` of :class:`Record`
- """
- action = '/v1/zones/%s' % zone.domain
- try:
- response = self.connection.request(action=action, method='GET')
- except NsOneException:
- e = sys.exc_info()[1]
- if e.message == 'zone not found':
- raise ZoneDoesNotExistError(value=e.message, driver=self,
- zone_id=zone.id)
- else:
- raise e
- records = self._to_records(items=response.parse_body()['records'],
- zone=zone)
-
- return records
-
- def get_record(self, zone_id, record_id):
- """
- :param zone_id: The id of the zone where to search for
- the record (e.g. example.com)
- :type zone_id: ``str``
- :param record_id: The type of record to search for
- (e.g. A, AAA, MX etc)
-
- :return: :class:`Record`
- """
- action = '/v1/zones/%s/%s/%s' % (zone_id, zone_id, record_id)
- try:
- response = self.connection.request(action=action, method='GET')
- except NsOneException:
- e = sys.exc_info()[1]
- if e.message == 'record not found':
- raise RecordDoesNotExistError(value=e.message, driver=self,
- record_id=record_id)
- else:
- raise e
- zone = self.get_zone(zone_id=zone_id)
- record = self._to_record(item=response.parse_body(), zone=zone)
-
- return record
-
- def delete_record(self, record):
- """
- :param record: Record to delete.
- :type record: :class:`Record`
-
- :return: Boolean
- """
- action = '/v1/zones/%s/%s/%s' % (record.zone.domain, record.name,
- record.type)
- try:
- response = self.connection.request(action=action, method='DELETE')
- except NsOneException:
- e = sys.exc_info()[1]
- if e.message == 'record not found':
- raise RecordDoesNotExistError(value=e.message, driver=self,
- record_id=record.id)
- else:
- raise e
-
- return response.status == httplib.OK
-
- def create_record(self, name, zone, type, data, extra=None):
- """
- :param name: Name of the record to create (e.g. foo).
- :type name: ``str``
- :param zone: Zone where the record should be created.
- :type zone: :class:`Zone`
- :param type: Type of record (e.g. A, MX etc)
- :type type: ``str``
- :param data: Data of the record (e.g. 127.0.0.1 for the A record)
- :type data: ``str``
- :param extra: Extra data needed to create different types of records
- :type extra: ``dict``
- :return: :class:`Record`
- """
- action = '/v1/zones/%s/%s/%s' % (zone.domain, '%s.%s' %
- (name, zone.domain), type)
- raw_data = {
- "answers": [
- {
- "answer": [
- data
- ], }
- ],
- "type": type,
- "domain": '%s.%s' % (name, zone.domain),
- "zone": zone.domain
- }
- if extra is not None and extra.get('answers'):
- raw_data['answers'] = extra.get('answers')
- post_data = json.dumps(raw_data)
- try:
- response = self.connection.request(action=action, method='PUT',
- data=post_data)
- except NsOneException:
- e = sys.exc_info()[1]
- if e.message == 'record already exists':
- raise RecordAlreadyExistsError(value=e.message, driver=self,
- record_id='')
- else:
- raise e
- record = self._to_record(item=response.parse_body(), zone=zone)
-
- return record
-
- def update_record(self, record, name, type, data, extra=None):
- """
- :param record: Record to update
- :type record: :class:`Record`
- :param name: Name of the record to update (e.g. foo).
- :type name: ``str``
- :param type: Type of record (e.g. A, MX etc)
- :type type: ``str``
- :param data: Data of the record (e.g. 127.0.0.1 for the A record)
- :type data: ``str``
- :param extra: Extra data needed to create different types of records
- :type extra: ``dict``
- :return: :class:`Record`
- """
- zone = record.zone
- action = '/v1/zones/%s/%s/%s' % (zone.domain, '%s.%s' %
- (name, zone.domain), type)
- raw_data = {
- "answers": [
- {
- "answer": [
- data
- ], }
- ]
- }
- if extra is not None and extra.get('answers'):
- raw_data['answers'] = extra.get('answers')
- post_data = json.dumps(raw_data)
- try:
- response = self.connection.request(action=action, data=post_data,
- method='POST')
- except NsOneException:
- e = sys.exc_info()[1]
- if e.message == 'record does not exist':
- raise RecordDoesNotExistError(value=e.message, driver=self,
- id=record.id)
- else:
- raise e
- record = self._to_record(item=response.parse_body(), zone=zone)
-
- return record
-
- def ex_zone_exists(self, zone_id, zones_list):
- """
- Function to check if a `Zone` object exists.
- :param zone_id: ID of the `Zone` object.
- :type zone_id: ``str``
-
- :param zones_list: A list containing `Zone` objects.
- :type zones_list: ``list``.
-
- :rtype: Returns `True` or `False`.
- """
- zone_ids = []
- for zone in zones_list:
- zone_ids.append(zone.id)
-
- return zone_id in zone_ids
-
- def _to_zone(self, item):
- common_attr = ['zone', 'id', 'type']
- extra = {}
- for key in item.keys():
- if key not in common_attr:
- extra[key] = item.get(key)
-
- zone = Zone(domain=item['zone'], id=item['id'], type=item.get('type'),
- extra=extra, ttl=extra.get('ttl'), driver=self)
-
- return zone
-
- def _to_zones(self, items):
- zones = []
- for item in items:
- zones.append(self._to_zone(item))
-
- return zones
-
- def _to_record(self, item, zone):
- common_attr = ['id', 'short_answers', 'answers', 'domain', 'type']
- extra = {}
- for key in item.keys():
- if key not in common_attr:
- extra[key] = item.get(key)
- if item.get('answers') is not None:
- data = item.get('answers')[0]['answer']
- else:
- data = item.get('short_answers')
- record = Record(id=item['id'], name=item['domain'], type=item['type'],
- data=data, zone=zone, driver=self,
- extra=extra)
-
- return record
-
- def _to_records(self, items, zone):
- records = []
- for item in items:
- records.append(self._to_record(item, zone))
-
- return records
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/pointdns.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/pointdns.py b/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/pointdns.py
deleted file mode 100644
index 1523bb9..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/pointdns.py
+++ /dev/null
@@ -1,791 +0,0 @@
-# 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.
-"""
-Point DNS Driver
-"""
-
-__all__ = [
- 'PointDNSException',
- 'Redirect',
- 'MailRedirect',
- 'PointDNSDriver'
-]
-
-import sys
-
-try:
- import simplejson as json
-except ImportError:
- import json
-
-from libcloud.utils.py3 import httplib
-from libcloud.common.types import ProviderError
-from libcloud.common.types import MalformedResponseError
-from libcloud.common.pointdns import PointDNSConnection
-from libcloud.common.exceptions import BaseHTTPError
-from libcloud.dns.types import Provider, RecordType
-from libcloud.dns.types import ZoneDoesNotExistError
-from libcloud.dns.types import RecordDoesNotExistError
-from libcloud.dns.base import DNSDriver, Zone, Record
-
-
-class PointDNSException(ProviderError):
-
- def __init__(self, value, http_code, driver=None):
- super(PointDNSException, self).__init__(value=value,
- http_code=http_code,
- driver=driver)
- self.args = (http_code, value)
-
-
-class Redirect(object):
- """
- Point DNS redirect.
- """
-
- def __init__(self, id, name, data, type, driver, zone, iframe=None,
- query=False):
- """
- :param id: Redirect id.
- :type id: ``str``
-
- :param name: The FQDN for the record.
- :type name: ``str``
-
- :param data: The data field. (redirect_to)
- :type data: ``str``
-
- :param type: The type of redirects 301, 302 or 0 for iframes.
- :type type: ``str``
-
- :param driver: DNSDriver instance.
- :type driver: :class:`DNSDriver`
-
- :param zone: Zone where redirect belongs.
- :type zone: :class:`Zone`
-
- :param iframe: Title of iframe (optional).
- :type iframe: ``str``
-
- :param query: boolean Information about including query string when
- redirecting. (optional).
- :type query: ``bool``
- """
- self.id = str(id) if id else None
- self.name = name
- self.data = data
- self.type = str(type) if type else None
- self.driver = driver
- self.zone = zone
- self.iframe = iframe
- self.query = query
-
- def update(self, data, name=None, type=None, iframe=None, query=None):
- return self.driver.ex_update_redirect(redirect=self, name=name,
- data=data, type=type,
- iframe=iframe, query=query)
-
- def delete(self):
- return self.driver.ex_delete_redirect(redirect=self)
-
- def __repr__(self):
- return ('<PointDNSRedirect: name=%s, data=%s, type=%s ...>' %
- (self.name, self.data, self.type))
-
-
-class MailRedirect(object):
- """
- Point DNS mail redirect.
- """
-
- def __init__(self, id, source, destination, zone, driver):
- """
- :param id: MailRedirect id.
- :type id: ``str``
-
- :param source: The source address of mail redirect.
- :type source: ``str``
-
- :param destination: The destination address of mail redirect.
- :type destination: ``str``
-
- :param zone: Zone where mail redirect belongs.
- :type zone: :class:`Zone`
-
- :param driver: DNSDriver instance.
- :type driver: :class:`DNSDriver`
- """
- self.id = str(id) if id else None
- self.source = source
- self.destination = destination
- self.zone = zone
- self.driver = driver
-
- def update(self, destination, source=None):
- return self.driver.ex_update_mail_redirect(mail_r=self,
- destination=destination,
- source=None)
-
- def delete(self):
- return self.driver.ex_delete_mail_redirect(mail_r=self)
-
- def __repr__(self):
- return ('<PointDNSMailRedirect: source=%s, destination=%s,zone=%s ...>'
- % (self.source, self.destination, self.zone.id))
-
-
-class PointDNSDriver(DNSDriver):
- type = Provider.POINTDNS
- name = 'Point DNS'
- website = 'https://pointhq.com/'
- connectionCls = PointDNSConnection
-
- RECORD_TYPE_MAP = {
- RecordType.A: 'A',
- RecordType.AAAA: 'AAAA',
- RecordType.ALIAS: 'ALIAS',
- RecordType.CNAME: 'CNAME',
- RecordType.MX: 'MX',
- RecordType.NS: 'NS',
- RecordType.PTR: 'PTR',
- RecordType.SRV: 'SRV',
- RecordType.SSHFP: 'SSHFP',
- RecordType.TXT: 'TXT'
- }
-
- def list_zones(self):
- """
- Return a list of zones.
-
- :return: ``list`` of :class:`Zone`
- """
- response = self.connection.request('/zones')
- zones = self._to_zones(response.object)
- return zones
-
- def list_records(self, zone):
- """
- Return a list of records for the provided zone.
-
- :param zone: Zone to list records for.
- :type zone: :class:`Zone`
-
- :return: ``list`` of :class:`Record`
- """
- response = self.connection.request('/zones/%s/records' % zone.id)
- records = self._to_records(response.object, zone)
- return records
-
- def get_zone(self, zone_id):
- """
- Return a Zone instance.
-
- :param zone_id: ID of the required zone
- :type zone_id: ``str``
-
- :rtype: :class:`Zone`
- """
- try:
- response = self.connection.request('/zones/%s' % zone_id)
- except MalformedResponseError:
- e = sys.exc_info()[1]
- if e.body == 'Not found':
- raise ZoneDoesNotExistError(driver=self,
- value="The zone doesn't exists",
- zone_id=zone_id)
- raise e
-
- zone = self._to_zone(response.object)
- return zone
-
- def get_record(self, zone_id, record_id):
- """
- Return a Record instance.
-
- :param zone_id: ID of the required zone
- :type zone_id: ``str``
-
- :param record_id: ID of the required record
- :type record_id: ``str``
-
- :rtype: :class:`Record`
- """
- try:
- response = self.connection.request('/zones/%s/records/%s' %
- (zone_id, record_id))
- except MalformedResponseError:
- e = sys.exc_info()[1]
- if e.body == 'Not found':
- raise RecordDoesNotExistError(value="Record doesn't exists",
- driver=self,
- record_id=record_id)
- raise e
-
- record = self._to_record(response.object, zone_id=zone_id)
- return record
-
- def create_zone(self, domain, type='master', ttl=None, extra=None):
- """
- Create a new zone.
-
- :param domain: Zone domain name (e.g. example.com)
- :type domain: ``str``
-
- :param type: Zone type (All zones are master by design).
- :type type: ``str``
-
- :param ttl: TTL for new records. (optional)
- :type ttl: ``int``
-
- :param extra: Extra attributes (driver specific). (optional)
- :type extra: ``dict``
-
- :rtype: :class:`Zone`
- """
- r_json = {'name': domain}
- if ttl is not None:
- r_json['ttl'] = ttl
- if extra is not None:
- r_json.update(extra)
- r_data = json.dumps({'zone': r_json})
- try:
- response = self.connection.request('/zones', method='POST',
- data=r_data)
- except BaseHTTPError:
- e = sys.exc_info()[1]
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- zone = self._to_zone(response.object)
- return zone
-
- def create_record(self, name, zone, type, data, extra=None):
- """
- Create a new record.
-
- :param name: Record name without the domain name (e.g. www).
- Note: If you want to create a record for a base domain
- name, you should specify empty string ('') for this
- argument.
- :type name: ``str``
-
- :param zone: Zone where the requested record is created.
- :type zone: :class:`Zone`
-
- :param type: DNS record type (A, AAAA, ...).
- :type type: :class:`RecordType`
-
- :param data: Data for the record (depends on the record type).
- :type data: ``str``
-
- :param extra: Extra attributes (driver specific). (optional)
- :type extra: ``dict``
-
- :rtype: :class:`Record`
- """
- r_json = {'name': name, 'data': data, 'record_type': type}
- if extra is not None:
- r_json.update(extra)
- r_data = json.dumps({'zone_record': r_json})
- try:
- response = self.connection.request('/zones/%s/records' % zone.id,
- method='POST', data=r_data)
- except BaseHTTPError:
- e = sys.exc_info()[1]
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- record = self._to_record(response.object, zone=zone)
- return record
-
- def update_zone(self, zone, domain, type='master', ttl=None, extra=None):
- """
- Update en existing zone.
-
- :param zone: Zone to update.
- :type zone: :class:`Zone`
-
- :param domain: Zone domain name (e.g. example.com)
- :type domain: ``str``
-
- :param type: Zone type (All zones are master by design).
- :type type: ``str``
-
- :param ttl: TTL for new records. (optional)
- :type ttl: ``int``
-
- :param extra: Extra attributes (group, user-id). (optional)
- :type extra: ``dict``
-
- :rtype: :class:`Zone`
- """
- r_json = {'name': domain}
- if extra is not None:
- r_json.update(extra)
- r_data = json.dumps({'zone': r_json})
- try:
- response = self.connection.request('/zones/%s' % zone.id,
- method='PUT', data=r_data)
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- if isinstance(e, MalformedResponseError) and e.body == 'Not found':
- raise ZoneDoesNotExistError(value="Zone doesn't exists",
- driver=self,
- zone_id=zone.id)
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- zone = self._to_zone(response.object)
- return zone
-
- def update_record(self, record, name, type, data, extra=None):
- """
- Update an existing record.
-
- :param record: Record to update.
- :type record: :class:`Record`
-
- :param name: Record name without the domain name (e.g. www).
- Note: If you want to create a record for a base domain
- name, you should specify empty string ('') for this
- argument.
- :type name: ``str``
-
- :param type: DNS record type (A, AAAA, ...).
- :type type: :class:`RecordType`
-
- :param data: Data for the record (depends on the record type).
- :type data: ``str``
-
- :param extra: (optional) Extra attributes (driver specific).
- :type extra: ``dict``
-
- :rtype: :class:`Record`
- """
- zone = record.zone
- r_json = {'name': name, 'data': data, 'record_type': type}
- if extra is not None:
- r_json.update(extra)
- r_data = json.dumps({'zone_record': r_json})
- try:
- response = self.connection.request('/zones/%s/records/%s' %
- (zone.id, record.id),
- method='PUT', data=r_data)
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- if isinstance(e, MalformedResponseError) and e.body == 'Not found':
- raise RecordDoesNotExistError(value="Record doesn't exists",
- driver=self,
- record_id=record.id)
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- record = self._to_record(response.object, zone=zone)
- return record
-
- def delete_zone(self, zone):
- """
- Delete a zone.
-
- Note: This will delete all the records belonging to this zone.
-
- :param zone: Zone to delete.
- :type zone: :class:`Zone`
-
- :rtype: ``bool``
- """
- try:
- self.connection.request('/zones/%s' % zone.id, method='DELETE')
- except MalformedResponseError:
- e = sys.exc_info()[1]
- if e.body == 'Not found':
- raise ZoneDoesNotExistError(driver=self,
- value="The zone doesn't exists",
- zone_id=zone.id)
- raise e
- return True
-
- def delete_record(self, record):
- """
- Delete a record.
-
- :param record: Record to delete.
- :type record: :class:`Record`
-
- :rtype: ``bool``
- """
- zone_id = record.zone.id
- record_id = record.id
- try:
- self.connection.request('/zones/%s/records/%s' % (zone_id,
- record_id),
- method='DELETE')
- except MalformedResponseError:
- e = sys.exc_info()[1]
- if e.body == 'Not found':
- raise RecordDoesNotExistError(value="Record doesn't exists",
- driver=self,
- record_id=record_id)
- raise e
- return True
-
- def ex_list_redirects(self, zone):
- """
- :param zone: Zone to list redirects for.
- :type zone: :class:`Zone`
-
- :rtype: ``list`` of :class:`Record`
- """
- response = self.connection.request('/zones/%s/redirects' % zone.id)
- redirects = self._to_redirects(response.object, zone)
- return redirects
-
- def ex_list_mail_redirects(self, zone):
- """
- :param zone: Zone to list redirects for.
- :type zone: :class:`Zone`
-
- :rtype: ``list`` of :class:`MailRedirect`
- """
- response = self.connection.request('/zones/%s/mail_redirects' %
- zone.id)
- mail_redirects = self._to_mail_redirects(response.object, zone)
- return mail_redirects
-
- def ex_create_redirect(self, redirect_to, name, type, zone, iframe=None,
- query=None):
- """
- :param redirect_to: The data field. (redirect_to)
- :type redirect_to: ``str``
-
- :param name: The FQDN for the record.
- :type name: ``str``
-
- :param type: The type of redirects 301, 302 or 0 for iframes.
- :type type: ``str``
-
- :param zone: Zone to list redirects for.
- :type zone: :class:`Zone`
-
- :param iframe: Title of iframe (optional).
- :type iframe: ``str``
-
- :param query: boolean Information about including query string when
- redirecting. (optional).
- :type query: ``bool``
-
- :rtype: :class:`Record`
- """
- r_json = {'name': name, 'redirect_to': redirect_to}
- if type is not None:
- r_json['redirect_type'] = type
- if iframe is not None:
- r_json['iframe_title'] = iframe
- if query is not None:
- r_json['redirect_query_string'] = query
- r_data = json.dumps({'zone_redirect': r_json})
- try:
- response = self.connection.request('/zones/%s/redirects' % zone.id,
- method='POST', data=r_data)
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- redirect = self._to_redirect(response.object, zone=zone)
- return redirect
-
- def ex_create_mail_redirect(self, destination, source, zone):
- """
- :param destination: The destination address of mail redirect.
- :type destination: ``str``
-
- :param source: The source address of mail redirect.
- :type source: ``str``
-
- :param zone: Zone to list redirects for.
- :type zone: :class:`Zone`
-
- :rtype: ``list`` of :class:`MailRedirect`
- """
- r_json = {'destination_address': destination, 'source_address': source}
- r_data = json.dumps({'zone_mail_redirect': r_json})
- try:
- response = self.connection.request('/zones/%s/mail_redirects' %
- zone.id, method='POST',
- data=r_data)
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- mail_redirect = self._to_mail_redirect(response.object, zone=zone)
- return mail_redirect
-
- def ex_get_redirect(self, zone_id, redirect_id):
- """
- :param zone: Zone to list redirects for.
- :type zone: :class:`Zone`
-
- :param redirect_id: Redirect id.
- :type redirect_id: ``str``
-
- :rtype: ``list`` of :class:`Redirect`
- """
- try:
- response = self.connection.request('/zones/%s/redirects/%s' %
- (zone_id, redirect_id))
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- if isinstance(e, MalformedResponseError) and e.body == 'Not found':
- raise PointDNSException(value='Couldn\'t found redirect',
- http_code=httplib.NOT_FOUND,
- driver=self)
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- redirect = self._to_redirect(response.object, zone_id=zone_id)
- return redirect
-
- def ex_get_mail_redirects(self, zone_id, mail_r_id):
- """
- :param zone: Zone to list redirects for.
- :type zone: :class:`Zone`
-
- :param mail_r_id: Mail redirect id.
- :type mail_r_id: ``str``
-
- :rtype: ``list`` of :class:`MailRedirect`
- """
- try:
- response = self.connection.request('/zones/%s/mail_redirects/%s' %
- (zone_id, mail_r_id))
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- if isinstance(e, MalformedResponseError) and e.body == 'Not found':
- raise PointDNSException(value='Couldn\'t found mail redirect',
- http_code=httplib.NOT_FOUND,
- driver=self)
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- mail_redirect = self._to_mail_redirect(response.object,
- zone_id=zone_id)
- return mail_redirect
-
- def ex_update_redirect(self, redirect, redirect_to=None, name=None,
- type=None, iframe=None, query=None):
- """
- :param redirect: Record to update
- :type id: :class:`Redirect`
-
- :param redirect_to: The data field. (optional).
- :type redirect_to: ``str``
-
- :param name: The FQDN for the record.
- :type name: ``str``
-
- :param type: The type of redirects 301, 302 or 0 for iframes.
- (optional).
- :type type: ``str``
-
- :param iframe: Title of iframe (optional).
- :type iframe: ``str``
-
- :param query: boolean Information about including query string when
- redirecting. (optional).
- :type query: ``bool``
-
- :rtype: ``list`` of :class:`Redirect`
- """
- zone_id = redirect.zone.id
- r_json = {}
- if redirect_to is not None:
- r_json['redirect_to'] = redirect_to
- if name is not None:
- r_json['name'] = name
- if type is not None:
- r_json['record_type'] = type
- if iframe is not None:
- r_json['iframe_title'] = iframe
- if query is not None:
- r_json['redirect_query_string'] = query
- r_data = json.dumps({'zone_redirect': r_json})
- try:
- response = self.connection.request('/zones/%s/redirects/%s' %
- (zone_id, redirect.id),
- method='PUT', data=r_data)
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- if isinstance(e, MalformedResponseError) and e.body == 'Not found':
- raise PointDNSException(value='Couldn\'t found redirect',
- http_code=httplib.NOT_FOUND,
- driver=self)
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- redirect = self._to_redirect(response.object, zone=redirect.zone)
- return redirect
-
- def ex_update_mail_redirect(self, mail_r, destination, source=None):
- """
- :param mail_r: Mail redirect to update
- :type mail_r: :class:`MailRedirect`
-
- :param destination: The destination address of mail redirect.
- :type destination: ``str``
-
- :param source: The source address of mail redirect. (optional)
- :type source: ``str``
-
- :rtype: ``list`` of :class:`MailRedirect`
- """
- zone_id = mail_r.zone.id
- r_json = {'destination_address': destination}
- if source is not None:
- r_json['source_address'] = source
- r_data = json.dumps({'zone_redirect': r_json})
- try:
- response = self.connection.request('/zones/%s/mail_redirects/%s' %
- (zone_id, mail_r.id),
- method='PUT', data=r_data)
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- if isinstance(e, MalformedResponseError) and e.body == 'Not found':
- raise PointDNSException(value='Couldn\'t found mail redirect',
- http_code=httplib.NOT_FOUND,
- driver=self)
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- mail_redirect = self._to_mail_redirect(response.object,
- zone=mail_r.zone)
- return mail_redirect
-
- def ex_delete_redirect(self, redirect):
- """
- :param mail_r: Redirect to delete
- :type mail_r: :class:`Redirect`
-
- :rtype: ``bool``
- """
- zone_id = redirect.zone.id
- redirect_id = redirect.id
- try:
- self.connection.request('/zones/%s/redirects/%s' % (zone_id,
- redirect_id), method='DELETE')
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- if isinstance(e, MalformedResponseError) and e.body == 'Not found':
- raise PointDNSException(value='Couldn\'t found redirect',
- http_code=httplib.NOT_FOUND,
- driver=self)
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- return True
-
- def ex_delete_mail_redirect(self, mail_r):
- """
- :param mail_r: Mail redirect to update
- :type mail_r: :class:`MailRedirect`
-
- :rtype: ``bool``
- """
- zone_id = mail_r.zone.id
- mail_r_id = mail_r.id
- try:
- self.connection.request('/zones/%s/mail_redirects/%s' % (zone_id,
- mail_r_id), method='DELETE')
- except (BaseHTTPError, MalformedResponseError):
- e = sys.exc_info()[1]
- if isinstance(e, MalformedResponseError) and e.body == 'Not found':
- raise PointDNSException(value='Couldn\'t found mail redirect',
- http_code=httplib.NOT_FOUND,
- driver=self)
- raise PointDNSException(value=e.message, http_code=e.code,
- driver=self)
- return True
-
- def _to_zones(self, data):
- zones = []
- for zone in data:
- _zone = self._to_zone(zone)
- zones.append(_zone)
-
- return zones
-
- def _to_zone(self, data):
- zone = data.get('zone')
- id = zone.get('id')
- name = zone.get('name')
- ttl = zone.get('ttl')
- extra = {'group': zone.get('group'),
- 'user-id': zone.get('user-id')}
-
- # All zones are a primary ones by design, so they
- # assume that are the master source of info about the
- # zone, which is the case when domain DNS records
- # points to PointDNS nameservers.
- type = 'master'
-
- return Zone(id=id, domain=name, type=type, ttl=ttl, driver=self,
- extra=extra)
-
- def _to_records(self, data, zone):
- records = []
- for item in data:
- record = self._to_record(item, zone=zone)
- records.append(record)
- return records
-
- def _to_record(self, data, zone_id=None, zone=None):
- if not zone: # We need zone_id or zone
- zone = self.get_zone(zone_id)
- record = data.get('zone_record')
- id = record.get('id')
- name = record.get('name')
- type = record.get('record_type')
- data = record.get('data')
- extra = {'ttl': record.get('ttl'),
- 'zone_id': record.get('zone_id'),
- 'aux': record.get('aux')}
- return Record(id=id, name=name, type=type, data=data, zone=zone,
- driver=self, ttl=record.get('ttl', None), extra=extra)
-
- def _to_redirects(self, data, zone):
- redirects = []
- for item in data:
- redirect = self._to_redirect(item, zone=zone)
- redirects.append(redirect)
- return redirects
-
- def _to_redirect(self, data, zone_id=None, zone=None):
- if not zone: # We need zone_id or zone
- zone = self.get_zone(zone_id)
- record = data.get('zone_redirect')
- id = record.get('id')
- name = record.get('name')
- redirect_to = record.get('redirect_to')
- type = record.get('redirect_type')
- iframe = record.get('iframe_title')
- query = record.get('redirect_query_string')
- return Redirect(id, name, redirect_to, type, self, zone,
- iframe=iframe, query=query)
-
- def _to_mail_redirects(self, data, zone):
- mail_redirects = []
- for item in data:
- mail_redirect = self._to_mail_redirect(item, zone=zone)
- mail_redirects.append(mail_redirect)
- return mail_redirects
-
- def _to_mail_redirect(self, data, zone_id=None, zone=None):
- if not zone: # We need zone_id or zone
- zone = self.get_zone(zone_id)
- record = data.get('zone_mail_redirect')
- id = record.get('id')
- destination = record.get('destination_address')
- source = record.get('source_address')
- return MailRedirect(id, source, destination, zone, self)
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/rackspace.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/rackspace.py b/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/rackspace.py
deleted file mode 100644
index 6d231e0..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/rackspace.py
+++ /dev/null
@@ -1,662 +0,0 @@
-# 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 copy
-
-from libcloud.utils.py3 import httplib
-from libcloud.common.openstack import OpenStackDriverMixin
-from libcloud.common.base import PollingConnection
-from libcloud.common.exceptions import BaseHTTPError
-from libcloud.common.types import LibcloudError
-from libcloud.utils.misc import merge_valid_keys, get_new_obj
-from libcloud.common.rackspace import AUTH_URL
-from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection
-from libcloud.compute.drivers.openstack import OpenStack_1_1_Response
-
-from libcloud.dns.types import Provider, RecordType
-from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
-from libcloud.dns.base import DNSDriver, Zone, Record
-
-__all__ = [
- 'RackspaceDNSResponse',
- 'RackspaceDNSConnection'
-]
-
-VALID_ZONE_EXTRA_PARAMS = ['email', 'comment', 'ns1']
-VALID_RECORD_EXTRA_PARAMS = ['ttl', 'comment', 'priority', 'created',
- 'updated']
-
-
-class RackspaceDNSResponse(OpenStack_1_1_Response):
- """
- Rackspace DNS Response class.
- """
-
- def parse_error(self):
- status = int(self.status)
- context = self.connection.context
- body = self.parse_body()
-
- 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'])
- if body:
- if 'code' and 'message' in body:
- err = '%s - %s (%s)' % (body['code'], body['message'],
- body['details'])
- return err
- elif 'validationErrors' in body:
- errors = [m for m in body['validationErrors']['messages']]
- err = 'Validation errors: %s' % ', '.join(errors)
- return err
-
- raise LibcloudError('Unexpected status code: %s' % (status))
-
-
-class RackspaceDNSConnection(OpenStack_1_1_Connection, PollingConnection):
- """
- Rackspace DNS Connection class.
- """
-
- responseCls = RackspaceDNSResponse
- XML_NAMESPACE = None
- poll_interval = 2.5
- timeout = 30
-
- auth_url = AUTH_URL
- _auth_version = '2.0'
-
- def __init__(self, *args, **kwargs):
- self.region = kwargs.pop('region', None)
- super(RackspaceDNSConnection, self).__init__(*args, **kwargs)
-
- def get_poll_request_kwargs(self, response, context, request_kwargs):
- job_id = response.object['jobId']
- kwargs = {'action': '/status/%s' % (job_id),
- 'params': {'showDetails': True}}
- return kwargs
-
- def has_completed(self, response):
- status = response.object['status']
- if status == 'ERROR':
- data = response.object['error']
-
- if 'code' and 'message' in data:
- message = '%s - %s (%s)' % (data['code'], data['message'],
- data['details'])
- else:
- message = data['message']
-
- raise LibcloudError(message,
- driver=self.driver)
-
- return status == 'COMPLETED'
-
- def get_endpoint(self):
- if '2.0' in self._auth_version:
- ep = self.service_catalog.get_endpoint(name='cloudDNS',
- service_type='rax:dns',
- region=None)
- else:
- raise LibcloudError("Auth version %s not supported" %
- (self._auth_version))
-
- public_url = ep.url
-
- # This is a nasty hack, but because of how global auth and old accounts
- # work, there is no way around it.
- if self.region == 'us':
- # Old UK account, which only has us endpoint in the catalog
- public_url = public_url.replace('https://lon.dns.api',
- 'https://dns.api')
- if self.region == 'uk':
- # Old US account, which only has uk endpoint in the catalog
- public_url = public_url.replace('https://dns.api',
- 'https://lon.dns.api')
-
- return public_url
-
-
-class RackspacePTRRecord(object):
- def __init__(self, id, ip, domain, driver, extra=None):
- self.id = str(id) if id else None
- self.ip = ip
- self.type = RecordType.PTR
- self.domain = domain
- self.driver = driver
- self.extra = extra or {}
-
- def update(self, domain, extra=None):
- return self.driver.ex_update_ptr_record(record=self, domain=domain,
- extra=extra)
-
- def delete(self):
- return self.driver.ex_delete_ptr_record(record=self)
-
- def __repr__(self):
- return ('<%s: ip=%s, domain=%s, provider=%s ...>' %
- (self.__class__.__name__, self.ip,
- self.domain, self.driver.name))
-
-
-class RackspaceDNSDriver(DNSDriver, OpenStackDriverMixin):
- name = 'Rackspace DNS'
- website = 'http://www.rackspace.com/'
- type = Provider.RACKSPACE
- connectionCls = RackspaceDNSConnection
-
- def __init__(self, key, secret=None, secure=True, host=None, port=None,
- region='us', **kwargs):
- valid_regions = self.list_regions()
- if region not in valid_regions:
- raise ValueError('Invalid region: %s' % (region))
-
- OpenStackDriverMixin.__init__(self, **kwargs)
- super(RackspaceDNSDriver, self).__init__(key=key, secret=secret,
- host=host, port=port,
- region=region)
-
- RECORD_TYPE_MAP = {
- RecordType.A: 'A',
- RecordType.AAAA: 'AAAA',
- RecordType.CNAME: 'CNAME',
- RecordType.MX: 'MX',
- RecordType.NS: 'NS',
- RecordType.PTR: 'PTR',
- RecordType.SRV: 'SRV',
- RecordType.TXT: 'TXT',
- }
-
- @classmethod
- def list_regions(cls):
- return ['us', 'uk']
-
- def iterate_zones(self):
- offset = 0
- limit = 100
- while True:
- params = {
- 'limit': limit,
- 'offset': offset,
- }
- response = self.connection.request(
- action='/domains', params=params).object
- zones_list = response['domains']
- for item in zones_list:
- yield self._to_zone(item)
-
- if _rackspace_result_has_more(response, len(zones_list), limit):
- offset += limit
- else:
- break
-
- def iterate_records(self, zone):
- self.connection.set_context({'resource': 'zone', 'id': zone.id})
- offset = 0
- limit = 100
- while True:
- params = {
- 'showRecord': True,
- 'limit': limit,
- 'offset': offset,
- }
- response = self.connection.request(
- action='/domains/%s' % (zone.id), params=params).object
- records_list = response['recordsList']
- records = records_list['records']
- for item in records:
- record = self._to_record(data=item, zone=zone)
- yield record
-
- if _rackspace_result_has_more(records_list, len(records), limit):
- offset += limit
- else:
- break
-
- def get_zone(self, zone_id):
- self.connection.set_context({'resource': 'zone', 'id': zone_id})
- response = self.connection.request(action='/domains/%s' % (zone_id))
- zone = self._to_zone(data=response.object)
- return zone
-
- def get_record(self, zone_id, record_id):
- zone = self.get_zone(zone_id=zone_id)
- self.connection.set_context({'resource': 'record', 'id': record_id})
- response = self.connection.request(action='/domains/%s/records/%s' %
- (zone_id, record_id)).object
- record = self._to_record(data=response, zone=zone)
- return record
-
- def create_zone(self, domain, type='master', ttl=None, extra=None):
- extra = extra if extra else {}
-
- # Email address is required
- if 'email' not in extra:
- raise ValueError('"email" key must be present in extra dictionary')
-
- payload = {'name': domain, 'emailAddress': extra['email'],
- 'recordsList': {'records': []}}
-
- if ttl:
- payload['ttl'] = ttl
-
- if 'comment' in extra:
- payload['comment'] = extra['comment']
-
- data = {'domains': [payload]}
- response = self.connection.async_request(action='/domains',
- method='POST', data=data)
- zone = self._to_zone(data=response.object['response']['domains'][0])
- return zone
-
- def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None):
- # Only ttl, comment and email address can be changed
- extra = extra if extra else {}
-
- if domain:
- raise LibcloudError('Domain cannot be changed', driver=self)
-
- data = {}
-
- if ttl:
- data['ttl'] = int(ttl)
-
- if 'email' in extra:
- data['emailAddress'] = extra['email']
-
- if 'comment' in extra:
- data['comment'] = extra['comment']
-
- type = type if type else zone.type
- ttl = ttl if ttl else zone.ttl
-
- self.connection.set_context({'resource': 'zone', 'id': zone.id})
- self.connection.async_request(action='/domains/%s' % (zone.id),
- method='PUT', data=data)
- merged = merge_valid_keys(params=copy.deepcopy(zone.extra),
- valid_keys=VALID_ZONE_EXTRA_PARAMS,
- extra=extra)
- updated_zone = get_new_obj(obj=zone, klass=Zone,
- attributes={'type': type,
- 'ttl': ttl,
- 'extra': merged})
- return updated_zone
-
- def create_record(self, name, zone, type, data, extra=None):
- # Name must be a FQDN - e.g. if domain is "foo.com" then a record
- # name is "bar.foo.com"
- extra = extra if extra else {}
-
- name = self._to_full_record_name(domain=zone.domain, name=name)
- data = {'name': name, 'type': self.RECORD_TYPE_MAP[type],
- 'data': data}
-
- if 'ttl' in extra:
- data['ttl'] = int(extra['ttl'])
-
- if 'priority' in extra:
- data['priority'] = int(extra['priority'])
-
- payload = {'records': [data]}
- self.connection.set_context({'resource': 'zone', 'id': zone.id})
- response = self.connection.async_request(action='/domains/%s/records'
- % (zone.id), data=payload,
- method='POST').object
- record = self._to_record(data=response['response']['records'][0],
- zone=zone)
- return record
-
- def update_record(self, record, name=None, type=None, data=None,
- extra=None):
- # Only data, ttl, and comment attributes can be modified, but name
- # attribute must always be present.
- extra = extra if extra else {}
-
- name = self._to_full_record_name(domain=record.zone.domain,
- name=record.name)
- payload = {'name': name}
-
- if data:
- payload['data'] = data
-
- if 'ttl' in extra:
- payload['ttl'] = extra['ttl']
-
- if 'comment' in extra:
- payload['comment'] = extra['comment']
-
- type = type if type is not None else record.type
- data = data if data else record.data
-
- self.connection.set_context({'resource': 'record', 'id': record.id})
- self.connection.async_request(action='/domains/%s/records/%s' %
- (record.zone.id, record.id),
- method='PUT', data=payload)
-
- merged = merge_valid_keys(params=copy.deepcopy(record.extra),
- valid_keys=VALID_RECORD_EXTRA_PARAMS,
- extra=extra)
- updated_record = get_new_obj(obj=record, klass=Record,
- attributes={'type': type,
- 'data': data,
- 'driver': self,
- 'extra': merged})
- return updated_record
-
- def delete_zone(self, zone):
- self.connection.set_context({'resource': 'zone', 'id': zone.id})
- self.connection.async_request(action='/domains/%s' % (zone.id),
- method='DELETE')
- return True
-
- def delete_record(self, record):
- self.connection.set_context({'resource': 'record', 'id': record.id})
- self.connection.async_request(action='/domains/%s/records/%s' %
- (record.zone.id, record.id),
- method='DELETE')
- return True
-
- def ex_iterate_ptr_records(self, device):
- """
- Return a generator to iterate over existing PTR Records.
-
- The ``device`` should be an instance of one of these:
- :class:`libcloud.compute.base.Node`
- :class:`libcloud.loadbalancer.base.LoadBalancer`
-
- And it needs to have the following ``extra`` fields set:
- service_name - the service catalog name for the device
- uri - the URI pointing to the GET endpoint for the device
-
- Those are automatically set for you if you got the device from
- the Rackspace driver for that service.
-
- For example:
- server = rs_compute.ex_get_node_details(id)
- ptr_iter = rs_dns.ex_list_ptr_records(server)
-
- loadbalancer = rs_lbs.get_balancer(id)
- ptr_iter = rs_dns.ex_list_ptr_records(loadbalancer)
-
- Note: the Rackspace DNS API docs indicate that the device 'href' is
- optional, but testing does not bear this out. It throws a
- 400 Bad Request error if you do not pass in the 'href' from
- the server or loadbalancer. So ``device`` is required.
-
- :param device: the device that owns the IP
- :rtype: ``generator`` of :class:`RackspacePTRRecord`
- """
- _check_ptr_extra_fields(device)
- params = {'href': device.extra['uri']}
-
- service_name = device.extra['service_name']
-
- # without a valid context, the 404 on empty list will blow up
- # in the error-handling code
- self.connection.set_context({'resource': 'ptr_records'})
- try:
- response = self.connection.request(
- action='/rdns/%s' % (service_name), params=params).object
- records = response['records']
- link = dict(rel=service_name, **params)
- for item in records:
- record = self._to_ptr_record(data=item, link=link)
- yield record
- except BaseHTTPError as exc:
- # 404 just means empty list
- if exc.code == 404:
- return
- raise
-
- def ex_get_ptr_record(self, service_name, record_id):
- """
- Get a specific PTR record by id.
-
- :param service_name: the service catalog name of the linked device(s)
- i.e. cloudLoadBalancers or cloudServersOpenStack
- :param record_id: the id (i.e. PTR-12345) of the PTR record
- :rtype: instance of :class:`RackspacePTRRecord`
- """
- self.connection.set_context({'resource': 'record', 'id': record_id})
- response = self.connection.request(
- action='/rdns/%s/%s' % (service_name, record_id)).object
- item = next(iter(response['recordsList']['records']))
- return self._to_ptr_record(data=item, link=response['link'])
-
- def ex_create_ptr_record(self, device, ip, domain, extra=None):
- """
- Create a PTR record for a specific IP on a specific device.
-
- The ``device`` should be an instance of one of these:
- :class:`libcloud.compute.base.Node`
- :class:`libcloud.loadbalancer.base.LoadBalancer`
-
- And it needs to have the following ``extra`` fields set:
- service_name - the service catalog name for the device
- uri - the URI pointing to the GET endpoint for the device
-
- Those are automatically set for you if you got the device from
- the Rackspace driver for that service.
-
- For example:
- server = rs_compute.ex_get_node_details(id)
- rs_dns.create_ptr_record(server, ip, domain)
-
- loadbalancer = rs_lbs.get_balancer(id)
- rs_dns.create_ptr_record(loadbalancer, ip, domain)
-
- :param device: the device that owns the IP
- :param ip: the IP for which you want to set reverse DNS
- :param domain: the fqdn you want that IP to represent
- :param extra: a ``dict`` with optional extra values:
- ttl - the time-to-live of the PTR record
- :rtype: instance of :class:`RackspacePTRRecord`
- """
- _check_ptr_extra_fields(device)
-
- if extra is None:
- extra = {}
-
- # the RDNS API reverse the name and data fields for PTRs
- # the record name *should* be the ip and the data the fqdn
- data = {
- "name": domain,
- "type": RecordType.PTR,
- "data": ip
- }
-
- if 'ttl' in extra:
- data['ttl'] = extra['ttl']
-
- payload = {
- "recordsList": {
- "records": [data]
- },
- "link": {
- "content": "",
- "href": device.extra['uri'],
- "rel": device.extra['service_name'],
- }
- }
- response = self.connection.async_request(
- action='/rdns', method='POST', data=payload).object
- item = next(iter(response['response']['records']))
- return self._to_ptr_record(data=item, link=payload['link'])
-
- def ex_update_ptr_record(self, record, domain=None, extra=None):
- """
- Update a PTR record for a specific IP on a specific device.
-
- If you need to change the domain or ttl, use this API to
- update the record by deleting the old one and creating a new one.
-
- :param record: the original :class:`RackspacePTRRecord`
- :param domain: the fqdn you want that IP to represent
- :param extra: a ``dict`` with optional extra values:
- ttl - the time-to-live of the PTR record
- :rtype: instance of :class:`RackspacePTRRecord`
- """
- if domain is not None and domain == record.domain:
- domain = None
-
- if extra is not None:
- extra = dict(extra)
- for key in extra:
- if key in record.extra and record.extra[key] == extra[key]:
- del extra[key]
-
- if domain is None and not extra:
- # nothing to do, it already matches
- return record
-
- _check_ptr_extra_fields(record)
- ip = record.ip
-
- self.ex_delete_ptr_record(record)
- # records have the same metadata in 'extra' as the original device
- # so you can pass the original record object in instead
- return self.ex_create_ptr_record(record, ip, domain, extra=extra)
-
- def ex_delete_ptr_record(self, record):
- """
- Delete an existing PTR Record
-
- :param record: the original :class:`RackspacePTRRecord`
- :rtype: ``bool``
- """
- _check_ptr_extra_fields(record)
- self.connection.set_context({'resource': 'record', 'id': record.id})
- self.connection.async_request(
- action='/rdns/%s' % (record.extra['service_name']),
- method='DELETE',
- params={'href': record.extra['uri'], 'ip': record.ip},
- )
- return True
-
- def _to_zone(self, data):
- id = data['id']
- domain = data['name']
- type = 'master'
- ttl = data.get('ttl', 0)
- extra = {}
-
- if 'emailAddress' in data:
- extra['email'] = data['emailAddress']
-
- if 'comment' in data:
- extra['comment'] = data['comment']
-
- zone = Zone(id=str(id), domain=domain, type=type, ttl=int(ttl),
- driver=self, extra=extra)
- return zone
-
- def _to_record(self, data, zone):
- id = data['id']
- fqdn = data['name']
- name = self._to_partial_record_name(domain=zone.domain, name=fqdn)
- type = self._string_to_record_type(data['type'])
- record_data = data['data']
- extra = {'fqdn': fqdn}
-
- for key in VALID_RECORD_EXTRA_PARAMS:
- if key in data:
- extra[key] = data[key]
-
- record = Record(id=str(id), name=name, type=type, data=record_data,
- zone=zone, driver=self, ttl=extra.get('ttl', None),
- extra=extra)
- return record
-
- def _to_ptr_record(self, data, link):
- id = data['id']
- ip = data['data']
- domain = data['name']
- extra = {'uri': link['href'], 'service_name': link['rel']}
-
- for key in VALID_RECORD_EXTRA_PARAMS:
- if key in data:
- extra[key] = data[key]
-
- record = RackspacePTRRecord(id=str(id), ip=ip, domain=domain,
- driver=self, extra=extra)
- return record
-
- def _to_full_record_name(self, domain, name):
- """
- Build a FQDN from a domain and record name.
-
- :param domain: Domain name.
- :type domain: ``str``
-
- :param name: Record name.
- :type name: ``str``
- """
- if name:
- name = '%s.%s' % (name, domain)
- else:
- name = domain
-
- return name
-
- def _to_partial_record_name(self, domain, name):
- """
- Remove domain portion from the record name.
-
- :param domain: Domain name.
- :type domain: ``str``
-
- :param name: Full record name (fqdn).
- :type name: ``str``
- """
- if name == domain:
- # Map "root" record names to None to be consistent with other
- # drivers
- return None
-
- # Strip domain portion
- name = name.replace('.%s' % (domain), '')
- return name
-
- def _ex_connection_class_kwargs(self):
- kwargs = self.openstack_connection_kwargs()
- kwargs['region'] = self.region
- return kwargs
-
-
-def _rackspace_result_has_more(response, result_length, limit):
- # If rackspace returns less than the limit, then we've reached the end of
- # the result set.
- if result_length < limit:
- return False
-
- # Paginated results return links to the previous and next sets of data, but
- # 'next' only exists when there is more to get.
- for item in response.get('links', ()):
- if item['rel'] == 'next':
- return True
- return False
-
-
-def _check_ptr_extra_fields(device_or_record):
- if not (hasattr(device_or_record, 'extra') and
- isinstance(device_or_record.extra, dict) and
- device_or_record.extra.get('uri') is not None and
- device_or_record.extra.get('service_name') is not None):
- raise LibcloudError("Can't create PTR Record for %s because it "
- "doesn't have a 'uri' and 'service_name' in "
- "'extra'" % device_or_record)
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/route53.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/route53.py b/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/route53.py
deleted file mode 100644
index 040cdbc..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/dns/drivers/route53.py
+++ /dev/null
@@ -1,548 +0,0 @@
-# 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__ = [
- 'Route53DNSDriver'
-]
-
-import base64
-import hmac
-import datetime
-import uuid
-import copy
-from libcloud.utils.py3 import httplib
-
-from hashlib import sha1
-
-try:
- from lxml import etree as ET
-except ImportError:
- from xml.etree import ElementTree as ET
-
-from libcloud.utils.py3 import b, urlencode
-
-from libcloud.utils.xml import findtext, findall, fixxpath
-from libcloud.dns.types import Provider, RecordType
-from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
-from libcloud.dns.base import DNSDriver, Zone, Record
-from libcloud.common.types import LibcloudError
-from libcloud.common.aws import AWSGenericResponse
-from libcloud.common.base import ConnectionUserAndKey
-
-
-API_VERSION = '2012-02-29'
-API_HOST = 'route53.amazonaws.com'
-API_ROOT = '/%s/' % (API_VERSION)
-
-NAMESPACE = 'https://%s/doc%s' % (API_HOST, API_ROOT)
-
-
-class InvalidChangeBatch(LibcloudError):
- pass
-
-
-class Route53DNSResponse(AWSGenericResponse):
- """
- Amazon Route53 response class.
- """
-
- namespace = NAMESPACE
- xpath = 'Error'
-
- exceptions = {
- 'NoSuchHostedZone': ZoneDoesNotExistError,
- 'InvalidChangeBatch': InvalidChangeBatch,
- }
-
-
-class Route53Connection(ConnectionUserAndKey):
- host = API_HOST
- responseCls = Route53DNSResponse
-
- def pre_connect_hook(self, params, headers):
- time_string = datetime.datetime.utcnow() \
- .strftime('%a, %d %b %Y %H:%M:%S GMT')
- headers['Date'] = time_string
- tmp = []
-
- signature = self._get_aws_auth_b64(self.key, time_string)
- auth = {'AWSAccessKeyId': self.user_id, 'Signature': signature,
- 'Algorithm': 'HmacSHA1'}
-
- for k, v in auth.items():
- tmp.append('%s=%s' % (k, v))
-
- headers['X-Amzn-Authorization'] = 'AWS3-HTTPS ' + ','.join(tmp)
-
- return params, headers
-
- def _get_aws_auth_b64(self, secret_key, time_string):
- b64_hmac = base64.b64encode(
- hmac.new(b(secret_key), b(time_string), digestmod=sha1).digest()
- )
-
- return b64_hmac.decode('utf-8')
-
-
-class Route53DNSDriver(DNSDriver):
- type = Provider.ROUTE53
- name = 'Route53 DNS'
- website = 'http://aws.amazon.com/route53/'
- connectionCls = Route53Connection
-
- RECORD_TYPE_MAP = {
- RecordType.A: 'A',
- RecordType.AAAA: 'AAAA',
- RecordType.CNAME: 'CNAME',
- RecordType.MX: 'MX',
- RecordType.NS: 'NS',
- RecordType.PTR: 'PTR',
- RecordType.SOA: 'SOA',
- RecordType.SPF: 'SPF',
- RecordType.SRV: 'SRV',
- RecordType.TXT: 'TXT',
- }
-
- def iterate_zones(self):
- return self._get_more('zones')
-
- def iterate_records(self, zone):
- return self._get_more('records', zone=zone)
-
- def get_zone(self, zone_id):
- self.connection.set_context({'zone_id': zone_id})
- uri = API_ROOT + 'hostedzone/' + zone_id
- data = self.connection.request(uri).object
- elem = findall(element=data, xpath='HostedZone',
- namespace=NAMESPACE)[0]
- return self._to_zone(elem)
-
- def get_record(self, zone_id, record_id):
- zone = self.get_zone(zone_id=zone_id)
- record_type, name = record_id.split(':', 1)
- if name:
- full_name = ".".join((name, zone.domain))
- else:
- full_name = zone.domain
- self.connection.set_context({'zone_id': zone_id})
- params = urlencode({
- 'name': full_name,
- 'type': record_type,
- 'maxitems': '1'
- })
- uri = API_ROOT + 'hostedzone/' + zone_id + '/rrset?' + params
- data = self.connection.request(uri).object
-
- record = self._to_records(data=data, zone=zone)[0]
-
- # A cute aspect of the /rrset filters is that they are more pagination
- # hints than filters!!
- # So will return a result even if its not what you asked for.
- record_type_num = self._string_to_record_type(record_type)
- if record.name != name or record.type != record_type_num:
- raise RecordDoesNotExistError(value='', driver=self,
- record_id=record_id)
-
- return record
-
- def create_zone(self, domain, type='master', ttl=None, extra=None):
- zone = ET.Element('CreateHostedZoneRequest', {'xmlns': NAMESPACE})
- ET.SubElement(zone, 'Name').text = domain
- ET.SubElement(zone, 'CallerReference').text = str(uuid.uuid4())
-
- if extra and 'Comment' in extra:
- hzg = ET.SubElement(zone, 'HostedZoneConfig')
- ET.SubElement(hzg, 'Comment').text = extra['Comment']
-
- uri = API_ROOT + 'hostedzone'
- data = ET.tostring(zone)
- rsp = self.connection.request(uri, method='POST', data=data).object
-
- elem = findall(element=rsp, xpath='HostedZone', namespace=NAMESPACE)[0]
- return self._to_zone(elem=elem)
-
- def delete_zone(self, zone, ex_delete_records=False):
- self.connection.set_context({'zone_id': zone.id})
-
- if ex_delete_records:
- self.ex_delete_all_records(zone=zone)
-
- uri = API_ROOT + 'hostedzone/%s' % (zone.id)
- response = self.connection.request(uri, method='DELETE')
- return response.status in [httplib.OK]
-
- def create_record(self, name, zone, type, data, extra=None):
- extra = extra or {}
- batch = [('CREATE', name, type, data, extra)]
- self._post_changeset(zone, batch)
- id = ':'.join((self.RECORD_TYPE_MAP[type], name))
- return Record(id=id, name=name, type=type, data=data, zone=zone,
- driver=self, ttl=extra.get('ttl', None), extra=extra)
-
- def update_record(self, record, name=None, type=None, data=None,
- extra=None):
- name = name or record.name
- type = type or record.type
- extra = extra or record.extra
-
- if not extra:
- extra = record.extra
-
- # Multiple value records need to be handled specially - we need to
- # pass values for other records as well
- multiple_value_record = record.extra.get('_multi_value', False)
- other_records = record.extra.get('_other_records', [])
-
- if multiple_value_record and other_records:
- self._update_multi_value_record(record=record, name=name,
- type=type, data=data,
- extra=extra)
- else:
- self._update_single_value_record(record=record, name=name,
- type=type, data=data,
- extra=extra)
-
- id = ':'.join((self.RECORD_TYPE_MAP[type], name))
- return Record(id=id, name=name, type=type, data=data, zone=record.zone,
- driver=self, ttl=extra.get('ttl', None), extra=extra)
-
- def delete_record(self, record):
- try:
- r = record
- batch = [('DELETE', r.name, r.type, r.data, r.extra)]
- self._post_changeset(record.zone, batch)
- except InvalidChangeBatch:
- raise RecordDoesNotExistError(value='', driver=self,
- record_id=r.id)
- return True
-
- def ex_create_multi_value_record(self, name, zone, type, data, extra=None):
- """
- Create a record with multiple values with a single call.
-
- :return: A list of created records.
- :rtype: ``list`` of :class:`libcloud.dns.base.Record`
- """
- extra = extra or {}
-
- attrs = {'xmlns': NAMESPACE}
- changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs)
- batch = ET.SubElement(changeset, 'ChangeBatch')
- changes = ET.SubElement(batch, 'Changes')
-
- change = ET.SubElement(changes, 'Change')
- ET.SubElement(change, 'Action').text = 'CREATE'
-
- rrs = ET.SubElement(change, 'ResourceRecordSet')
- ET.SubElement(rrs, 'Name').text = name + '.' + zone.domain
- ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type]
- ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0'))
-
- rrecs = ET.SubElement(rrs, 'ResourceRecords')
-
- # Value is provided as a multi line string
- values = [value.strip() for value in data.split('\n') if
- value.strip()]
-
- for value in values:
- rrec = ET.SubElement(rrecs, 'ResourceRecord')
- ET.SubElement(rrec, 'Value').text = value
-
- uri = API_ROOT + 'hostedzone/' + zone.id + '/rrset'
- data = ET.tostring(changeset)
- self.connection.set_context({'zone_id': zone.id})
- self.connection.request(uri, method='POST', data=data)
-
- id = ':'.join((self.RECORD_TYPE_MAP[type], name))
-
- records = []
- for value in values:
- record = Record(id=id, name=name, type=type, data=value, zone=zone,
- driver=self, ttl=extra.get('ttl', None),
- extra=extra)
- records.append(record)
-
- return records
-
- def ex_delete_all_records(self, zone):
- """
- Remove all the records for the provided zone.
-
- :param zone: Zone to delete records for.
- :type zone: :class:`Zone`
- """
- deletions = []
- for r in zone.list_records():
- if r.type in (RecordType.NS, RecordType.SOA):
- continue
- deletions.append(('DELETE', r.name, r.type, r.data, r.extra))
-
- if deletions:
- self._post_changeset(zone, deletions)
-
- def _update_single_value_record(self, record, name=None, type=None,
- data=None, extra=None):
- batch = [
- ('DELETE', record.name, record.type, record.data, record.extra),
- ('CREATE', name, type, data, extra)
- ]
-
- return self._post_changeset(record.zone, batch)
-
- def _update_multi_value_record(self, record, name=None, type=None,
- data=None, extra=None):
- other_records = record.extra.get('_other_records', [])
-
- attrs = {'xmlns': NAMESPACE}
- changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs)
- batch = ET.SubElement(changeset, 'ChangeBatch')
- changes = ET.SubElement(batch, 'Changes')
-
- # Delete existing records
- change = ET.SubElement(changes, 'Change')
- ET.SubElement(change, 'Action').text = 'DELETE'
-
- rrs = ET.SubElement(change, 'ResourceRecordSet')
-
- if record.name:
- record_name = record.name + '.' + record.zone.domain
- else:
- record_name = record.zone.domain
-
- ET.SubElement(rrs, 'Name').text = record_name
- ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[record.type]
- ET.SubElement(rrs, 'TTL').text = str(record.extra.get('ttl', '0'))
-
- rrecs = ET.SubElement(rrs, 'ResourceRecords')
-
- rrec = ET.SubElement(rrecs, 'ResourceRecord')
- ET.SubElement(rrec, 'Value').text = record.data
-
- for other_record in other_records:
- rrec = ET.SubElement(rrecs, 'ResourceRecord')
- ET.SubElement(rrec, 'Value').text = other_record['data']
-
- # Re-create new (updated) records. Since we are updating a multi value
- # record, only a single record is updated and others are left as is.
- change = ET.SubElement(changes, 'Change')
- ET.SubElement(change, 'Action').text = 'CREATE'
-
- rrs = ET.SubElement(change, 'ResourceRecordSet')
-
- if name:
- record_name = name + '.' + record.zone.domain
- else:
- record_name = record.zone.domain
-
- ET.SubElement(rrs, 'Name').text = record_name
- ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type]
- ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0'))
-
- rrecs = ET.SubElement(rrs, 'ResourceRecords')
-
- rrec = ET.SubElement(rrecs, 'ResourceRecord')
- ET.SubElement(rrec, 'Value').text = data
-
- for other_record in other_records:
- rrec = ET.SubElement(rrecs, 'ResourceRecord')
- ET.SubElement(rrec, 'Value').text = other_record['data']
- uri = API_ROOT + 'hostedzone/' + record.zone.id + '/rrset'
- data = ET.tostring(changeset)
- self.connection.set_context({'zone_id': record.zone.id})
- response = self.connection.request(uri, method='POST', data=data)
-
- return response.status == httplib.OK
-
- def _post_changeset(self, zone, changes_list):
- attrs = {'xmlns': NAMESPACE}
- changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs)
- batch = ET.SubElement(changeset, 'ChangeBatch')
- changes = ET.SubElement(batch, 'Changes')
-
- for action, name, type_, data, extra in changes_list:
- change = ET.SubElement(changes, 'Change')
- ET.SubElement(change, 'Action').text = action
-
- rrs = ET.SubElement(change, 'ResourceRecordSet')
-
- if name:
- record_name = name + '.' + zone.domain
- else:
- record_name = zone.domain
-
- ET.SubElement(rrs, 'Name').text = record_name
- ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type_]
- ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0'))
-
- rrecs = ET.SubElement(rrs, 'ResourceRecords')
- rrec = ET.SubElement(rrecs, 'ResourceRecord')
- if 'priority' in extra:
- data = '%s %s' % (extra['priority'], data)
- ET.SubElement(rrec, 'Value').text = data
-
- uri = API_ROOT + 'hostedzone/' + zone.id + '/rrset'
- data = ET.tostring(changeset)
- self.connection.set_context({'zone_id': zone.id})
- response = self.connection.request(uri, method='POST', data=data)
-
- return response.status == httplib.OK
-
- def _to_zones(self, data):
- zones = []
- for element in data.findall(fixxpath(xpath='HostedZones/HostedZone',
- namespace=NAMESPACE)):
- zones.append(self._to_zone(element))
-
- return zones
-
- def _to_zone(self, elem):
- name = findtext(element=elem, xpath='Name', namespace=NAMESPACE)
- id = findtext(element=elem, xpath='Id',
- namespace=NAMESPACE).replace('/hostedzone/', '')
- comment = findtext(element=elem, xpath='Config/Comment',
- namespace=NAMESPACE)
- resource_record_count = int(findtext(element=elem,
- xpath='ResourceRecordSetCount',
- namespace=NAMESPACE))
-
- extra = {'Comment': comment, 'ResourceRecordSetCount':
- resource_record_count}
-
- zone = Zone(id=id, domain=name, type='master', ttl=0, driver=self,
- extra=extra)
- return zone
-
- def _to_records(self, data, zone):
- records = []
- elems = data.findall(
- fixxpath(xpath='ResourceRecordSets/ResourceRecordSet',
- namespace=NAMESPACE))
- for elem in elems:
- record_set = elem.findall(fixxpath(
- xpath='ResourceRecords/ResourceRecord',
- namespace=NAMESPACE))
- record_count = len(record_set)
- multiple_value_record = (record_count > 1)
-
- record_set_records = []
-
- for index, record in enumerate(record_set):
- # Need to special handling for records with multiple values for
- # update to work correctly
- record = self._to_record(elem=elem, zone=zone, index=index)
- record.extra['_multi_value'] = multiple_value_record
-
- if multiple_value_record:
- record.extra['_other_records'] = []
-
- record_set_records.append(record)
-
- # Store reference to other records so update works correctly
- if multiple_value_record:
- for index in range(0, len(record_set_records)):
- record = record_set_records[index]
-
- for other_index, other_record in \
- enumerate(record_set_records):
- if index == other_index:
- # Skip current record
- continue
-
- extra = copy.deepcopy(other_record.extra)
- extra.pop('_multi_value')
- extra.pop('_other_records')
-
- item = {'name': other_record.name,
- 'data': other_record.data,
- 'type': other_record.type,
- 'extra': extra}
- record.extra['_other_records'].append(item)
-
- records.extend(record_set_records)
-
- return records
-
- def _to_record(self, elem, zone, index=0):
- name = findtext(element=elem, xpath='Name',
- namespace=NAMESPACE)
- name = name[:-len(zone.domain) - 1]
-
- type = self._string_to_record_type(findtext(element=elem, xpath='Type',
- namespace=NAMESPACE))
- ttl = findtext(element=elem, xpath='TTL', namespace=NAMESPACE)
- if ttl is not None:
- ttl = int(ttl)
-
- value_elem = elem.findall(
- fixxpath(xpath='ResourceRecords/ResourceRecord',
- namespace=NAMESPACE))[index]
- data = findtext(element=(value_elem), xpath='Value',
- namespace=NAMESPACE)
-
- extra = {'ttl': ttl}
-
- if type == 'MX':
- split = data.split()
- priority, data = split
- extra['priority'] = int(priority)
- elif type == 'SRV':
- split = data.split()
- priority, weight, port, data = split
- extra['priority'] = int(priority)
- extra['weight'] = int(weight)
- extra['port'] = int(port)
-
- id = ':'.join((self.RECORD_TYPE_MAP[type], name))
- record = Record(id=id, name=name, type=type, data=data, zone=zone,
- driver=self, ttl=extra.get('ttl', None), extra=extra)
- return record
-
- def _get_more(self, rtype, **kwargs):
- exhausted = False
- last_key = None
- while not exhausted:
- items, last_key, exhausted = self._get_data(rtype, last_key,
- **kwargs)
- for item in items:
- yield item
-
- def _get_data(self, rtype, last_key, **kwargs):
- params = {}
- if last_key:
- params['name'] = last_key
- path = API_ROOT + 'hostedzone'
-
- if rtype == 'zones':
- response = self.connection.request(path, params=params)
- transform_func = self._to_zones
- elif rtype == 'records':
- zone = kwargs['zone']
- path += '/%s/rrset' % (zone.id)
- self.connection.set_context({'zone_id': zone.id})
- response = self.connection.request(path, params=params)
- transform_func = self._to_records
-
- if response.status == httplib.OK:
- is_truncated = findtext(element=response.object,
- xpath='IsTruncated',
- namespace=NAMESPACE)
- exhausted = is_truncated != 'true'
- last_key = findtext(element=response.object,
- xpath='NextRecordName',
- namespace=NAMESPACE)
- items = transform_func(data=response.object, **kwargs)
- return items, last_key, exhausted
- else:
- return [], None, True