Source code for CloudDNS

#!/usr/bin/python

# Copyright 2012 Rackspace Hosting {{{
#
# Contact - Nate House nathan.house@rackspace.com
#
#   Licensed 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.
#
# }}}

from Cloud import *

#Setup logger.  Root logger config in _Globals.py
log = logging.getLogger(__name__)
#log.setLevel(logging.DEBUG)

[docs]class CloudDNS(Cloud): """ A class that handles actions to Cloud DNS via public methods listed. """ service = "DNS" #Limits{{{
[docs] def getLimits(self, type=None): """ Lists all current api limits for CloudDB. Passing type=list_types will show all available types of limits and passing type=<type> will show you assigned limits for that type. Arguments: type -- Limit type(string)(Optional) Returns: JSON results as a python dict """ if type is not None: if re.search("list_types", str(type), re.IGNORECASE): self.baseURL('limits/types') else: self.baseURL('limits/'+str(type).lower()) else: self.baseURL('limits') log.info("getLimits GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True) #}}} #Domains{{{
[docs] def getDomains(self, name=None): """ Lists all account domains. Filter by name, if specified. Use getDomainsId for more detailed response. Arguments: name -- Domain name(string) Returns: JSON results as a python dict """ self.baseURL('domains') self.queryVar('name',name) log.info("getDomains GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True)
[docs] def getDomain(self, domainId, attrDict={}): """ List details for a specific domain, using the showRecords and showSubdomains parameters that specify whether to request information for records and subdomains. Arguments: domainId -- attrDict -- showRecords -- (Optional) showSubdomains -- (Optional) Returns: JSON results as python dict """ self.baseURL('domains/'+str(domainId)) self.attrDict = attrDict self.queryDict() log.info("getDomain GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True)
[docs] def getDomainChanges(self, domainId, changeSince): """ Show all changes to the specified domain since the specified date/time in ISO format(2011-09-13T00:00:00-0500) Arguments: domainId -- changeSince -- format 2011-05-19T08:07:08-0500 etc Returns: JSON results as python dict """ self.baseURL('domains/'+str(domainId)+'/changes') self.queryVar('since',changeSince) log.info("getDomainChanges GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True)
[docs] def getDomainExport(self, domainId): """ Export details of the specified domain id. Arguments: domainId -- Returns: JSON results as python dict """ self.baseURL('domains/'+str(domainId)+'/export') log.info("getDomainExport GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True)
[docs] def createDomains(self, attrList, returnResults=False): """ Create domain requests given the provided info. The recordsList is a list of "records" using name, type(A,CNAME, etc), data and ttl. The subdomains is a list of "domains" using name, comment and emailAddress. See api docs for examples. Arguments: attrList: python list of dictionaries: name -- (Required) emailAddress -- (Required) ttl -- (Optional) commment -- (Optional) #recordsList -- (Optional) #subdomains -- (Optional) returnResults -- True / False - receive the Async Json (True) or the Response Code (Optional) Returns: Depends on returnResults arg. """ self.baseURL('domains') self.postKey = 'domains' self.attrList = attrList self.postKeyListDict() log.info("createDomains POST to %s with data - %s" % (self.endpoint, str(self.postData))) return apiRequest(self, self.endpoint, "POST", self.postData, returnResults=returnResults)
[docs] def createDomain(self, name, email, attrDict={}, returnResults=False): """ Create domain request given the provided info. The recordsList is a list of "records" using name, type(A,CNAME, etc), data and ttl. The subdomains is a list of "domains" using name, comment and emailAddress. See api docs for examples. Arguments: name -- (Required) email -- (Required) attrDict: python dictionary: ttl -- (Optional) commment -- (Optional) #recordsList -- (Optional) #subdomains -- (Optional) returnResults -- True / False - receive the Async Json (True) or the Response Code (Optional) Returns: Depends on returnResults arg. """ attrDict['name'] = name attrDict['emailAddress'] = email attrList = [attrDict] log.info("createDomain calling createDomains with %s" % str(attrList)) return self.createDomains(attrList, returnResults)
[docs] def importDomain(self, contents, contentType="BIND_9"): """ Import a new domain with the configuration specified by the request. Currently "BIND_9" is the only type supported and is defaulted to. Arguments: contentType -- contents -- Returns: JSON results as a python dict """ self.baseURL('domains/import') self.postKey = 'domains' attrList = [{'contentType':contentType,'contents':contents}] self.attrList = attrList self.postKeyListDict() log.info("importDomain POST to %s with data - %s" % (self.endpoint, str(self.postData))) return apiRequest(self, self.endpoint, "POST", self.postData, returnResults=True)
[docs] def updateDomains(self, domainList): """ Update the configuration of a domain or domains. This allows for updating of comments, ttl's or emailAddresses set on the domain. Domain dict should include id and optionally comment, ttl and emailAddress Arguments: domainList -- id -- emailAddress -- (Optional) ttl -- (Optional) comment -- (Optional) Returns: JSON results as a python dict """ if len(domainList) > 1: #updating multiple log.info("updateDomains passed multiple domains") self.baseURL('domains') self.postKey = 'domains' self.postKeyListDict() else: #updating just 1 log.info('updateDomains passed 1 domain') self.baseURL('domains/'+str(domainList[0]['id'])) del domainList[0]['id'] self.attrDict = domainList[0] self.postDict() log.info("updateDomains PUT to %s with data - %s" % (self.endpoint, str(self.postData))) return apiRequest(self, self.endpoint, "PUT", self.postData, returnResults=True)
[docs] def updateDomain(self, domainId, domainDict={}): """ Update the configuration of a domain. This allows for updating of comments, ttl's or emailAddresses set on the domain. Domain dict should include id and optionally comment, ttl and emailAddress Arguments: domainId -- Domain id(int) domainDict -- Dictionary containing optionally:(dict) email -- (Optional) ttl -- (Optional) comment -- (Optional) Returns: JSON results as a python dict """ domainDict['id'] = domainId domainList = [domainDict] log.info("updateDomain calling updateDomains with %s" % str(domainList)) return self.updateDomains(domainList)
[docs] def deleteDomain(self, domainId, deleteSubdomains=False, returnResults=False): """ Remove domain from account. Pass True to delete subdomains. Arguments: domainId -- Domain id(int) deleteSubdomains -- Boolean(Optional) returnResults -- True / False - receive the Async Json (True) or the Response Code (Optional) Returns: Depends on returnResults arg. """ log.info("deleteDomain calling deleteDomains with %s" % str(domainId)) return self.deleteDomains([domainId],deleteSubdomains,returnResults)
[docs] def deleteDomains(self, domainList, deleteSubdomains=False, returnResults=False): """ Remove domain(s) from account. Pass True to delete subdomains. Arguments: domainList -- list of domain ids to delete deleteSubdomains -- Boolean(Optional) returnResults -- True / False - receive the Async Json (True) or the Response Code (Optional) Returns: Depends on returnResults arg. """ self.baseURL('domains') self.queryVar('id',str(domainList[0])) if len(domainList) > 1: for i in range(1,len(domainList)): self.queryVar('id',str(domainList[i])) if deleteSubdomains: self.queryVar('deleteSubdomains','true') log.info("deleteDomain DELETE to %s" % self.endpoint) return apiRequest(self, self.endpoint, "DELETE", returnResults=returnResults) #}}} #Subdomains{{{
[docs] def getSubdomains(self, domainId): """ List domains that are subdomains of the specified domain. Arguments: domainId -- Domain id Returns: JSON results as python dict """ self.baseURL('domains/'+str(domainId)+'/subdomains') log.info("getSubdomains GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True) #}}} #Records{{{
[docs] def getRecord(self, domainId, recordId=None): """ List all records configured for the domain. SOA cannot be modified. Pass recordId to get record details. Arguments: domainId -- Domain id recordId -- Record id """ if recordId is not None: self.baseURL('domains/'+str(domainId)+'/records/'+str(recordId)) else: self.baseURL('domains/'+str(domainId)+'/records') log.info("getRecord GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True)
[docs] def getRecords(self, domainId, recordType, attrDict={}): #name=None, data=None): """ List all records for the specified domain of the specified type that match the specified name and/or data. Arguments: domainId -- recordType -- attrDict: name -- (Optional) data -- (Optional) Returns: JSON results as python dict """ self.baseURL('domains/'+str(domainId)+'/records') self.queryVar('type',recordType) self.attrDict = attrDict self.queryDict() log.info("getRecords GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True)
[docs] def createRecords(self, domainId, recordList,returnResults=False): """ Add new record(s) to the specified domains in a "records" list with name, type and data required. Arguments: domainId -- Domain Id recordList -- Python List of Dictionaries: type -- Specifies the record type to add. name -- Specifies the name for the domain or subdomain. Must be a valid domain name. data -- The data field for PTR, A, and AAAA records must be a valid IPv4 or IPv6 IP address priority -- (MX and SRV records only) Must be an integer from 0 to 65535. ttl -- Must be greater than 300. Defaults to the domain TTL or 3600 (Optional) comment -- If included, its length must be less than or equal to 160 characters. (Optional) returnResults -- True / False - receive the Async Json (True) or the Response Code (Optional) Returns: Depends on returnResults arg. """ self.baseURL('domains/'+str(domainId)+'/records') self.attrList = recordList self.postKey = 'records' self.postKeyListDict() log.info("createRecords POST call to %s with data - %s" % (self.endpoint, str(self.postData))) return apiRequest(self, self.endpoint, "POST", self.postData, returnResults=returnResults)
[docs] def createRecord(self, domainId, type, name, data, recordDict={},returnResults=False): """ Add new record to the specified domains in a "records" list with name, type and data required. Arguments: domainId -- Domain Id type -- Specifies the record type to add. name -- Specifies the name for the domain or subdomain. Must be a valid domain name. data -- The data field for PTR, A, and AAAA records must be a valid IPv4 or IPv6 IP address recordDict -- priority -- (MX and SRV records only) Must be an integer from 0 to 65535. ttl -- Must be greater than 300. Defaults to the domain TTL or 3600 (Optional) comment -- If included, its length must be less than or equal to 160 characters. (Optional) returnResults -- True / False - receive the Async Json (True) or the Response Code (Optional) Returns: Depends on returnResults arg. """ recordDict['type'] = type recordDict['name'] = name recordDict['data'] = data recordList = [recordDict] return self.createRecords(domainId,recordList,returnResults)
[docs] def updateRecords(self, domainId, recordList): """ Modify the configuration of records in the domain. Arguments: domainId -- Domain Id recordList -- rId -- Record Id type -- Specifies the record type to add. name -- Specifies the name for the domain or subdomain. Must be a valid domain name. data -- The data field for PTR, A, and AAAA records must be a valid IPv4 or IPv6 IP address priority -- (MX and SRV records only) Must be an integer from 0 to 65535. ttl -- Must be greater than 300. Defaults to the domain TTL or 3600 (Optional) comment -- If included, its length must be less than or equal to 160 characters. (Optional) Returns: JSON results as python dict """ if len(recordList) > 1: self.baseURL('domains/'+str(domainId)+'/records') self.postKey = 'records' self.attrList = recordList self.postKeyListDict() else: recordDict = recordList[0] self.baseURL('domains/'+str(domainId)+'/records/'+str(recordDict['id'])) del recordDict['id'] self.attrDict = recordDict self.postDict() log.info("updateRecords PUT to %s with data - %s" % (self.endpoint, str(self.postData))) return apiRequest(self, self.endpoint, "PUT", self.postData, returnResults=True)
[docs] def updateRecord(self, domainId, rId, recordDict): """ Modify the configuration of records in the domain. Arguments: domainId -- Domain Id rId -- Record Id recordDict -- type -- Specifies the record type to add. name -- Specifies the name for the domain or subdomain. Must be a valid domain name. data -- The data field for PTR, A, and AAAA records must be a valid IPv4 or IPv6 IP address priority -- (MX and SRV records only) Must be an integer from 0 to 65535. ttl -- Must be greater than 300. Defaults to the domain TTL or 3600 (Optional) comment -- If included, its length must be less than or equal to 160 characters. (Optional) Returns: JSON results as python dict """ recordDict['id'] = rId #recordDict['type'] = type #recordDict['name'] = name recordList = [recordDict] return self.updateRecords(domainId,recordList)
[docs] def deleteRecords(self, domainId, recordIdList,returnResults=False): """ Remove records from the domain. Arguments: domainId -- recordIdList -- List containing record ids """ if len(recordIdList) > 1: self.baseURL('domains/'+str(domainId)+'/records') for i in range(0,len(recordIdList)): self.queryVar('id',recordIdList[i]) else: self.baseURL('domains/'+str(domainId)+'/records/'+str(recordIdList[0])) log.info("deleteRecords DELETE to %s" % self.endpoint) return apiRequest(self, self.endpoint, "DELETE", returnResults=returnResults)
[docs] def deleteRecord(self, domainId, recordId, returnResults=False): """ Remove a record from the domain. Arguments: domainId -- Domain Id recordId -- Record Id """ recordIdList = [recordId] return self.deleteRecords(domainId,recordIdList,returnResults) #}}} #Rdns{{{
[docs] def getRdns(self, serviceType, deviceUri, recordId=None): """ List all PTR records configured for a Rackspace Cloud device or details on a specified record. Arguments: serviceType -- Current available options are cloudServersOpenStack or cloudLoadBalancers deviceUri -- Device href for associated service recordId -- Id specified in ptr record listing Returns: JSON results as python dict """ if recordId is None: endpoint = self.publicURL + "/rdns/%s?href=%s" % (str(serviceType), str(deviceUri)) else: endpoint = self.publicURL + "/rdns/%s/%s?href=%s" % (str(serviceType), str(recordId), str(deviceUri)) log.info("getRdns GET to %s" % endpoint) return apiRequest(self, endpoint, "GET", returnResults=True)
[docs] def createRdns(self, recordList, serviceType, deviceUri): """ Add new PTR record(s) for the specified Cloud device. Arguments: recordList -- { 'records': [ { 'name': required, 'type': 'PTR', 'data': required, 'ttl': optional } ] } etc serviceType -- cloudServersOpenStack or cloudLoadBalancers deviceUri -- Uri from service Returns: JSON result as python dict """ data = { } endpoint = self.publicURL + "/rdns" data['recordsList'] = recordList data['link'] = { 'content': '', 'href':str(deviceUri), 'rel': str(deviceUri) } log.info("createRdns POST to %s with data - %s" % (endpoint, str(data))) return apiRequest(self, endpoint, "POST", data, returnResults=True)
[docs] def updateRdns(self, recordList, serviceType, deviceUri): """ Modify existing PTR record(s) for specified Cloud device(s). Arguments: recordList -- { 'records': [ { 'name': required, 'id': required, 'type': 'PTR', 'data': required, 'ttl': optional } ] } etc serviceType -- cloudServersOpenStack or cloudLoadBalancers deviceUri -- Uri from service Returns: JSON result as python dict """ #self.baseURL('rdns') data = { } endpoint = self.publicURL + "/rdns" data['recordsList'] = recordList data['link'] = { 'content': '', 'href':str(deviceUri), 'rel': str(deviceUri) } log.info("updateRdns PUT to %s with data - %s" % (endpoint, str(data))) return apiRequest(self, endpoint, "PUT", data, returnResults=True)
[docs] def deleteRdns(self, serviceType, deviceUri, ip=None): """ Remove one or all PTR records associated with a Rackspace Cloud device. Use the optional ip query parameter to specify a specific record to delete. Omitting this parameter removes all PTR records associated with the specified device. Arguments: serviceType -- cloudServersOpenStack or cloudLoadBalancers deviceUri -- Uri from service ip -- Optional ipv4 or ipv6 addy Returns: status code """ endpoint = self.publicURL + "/rdns/%s?href=%s" % (str(serviceType), str(deviceUri)) if ip is not None: endpoint = endpoint + "&ip=%s" % str(ip) log.info("deleteRdns DELETE to %s" % endpoint) return apiRequest(self, endpoint, "DELETE") #}}}
[docs] def getAsync(self, url, detail=False): """ List status of the specified asynchronous request. Display details, as specified by the showDetails parameter. Arguments: url -- callbackUrl(string) detail -- (bool) Returns: JSON results as python dict """ self.baseURL(url) self.queryVar('showDetails',str(detail)) self.queryVar('showDetails',str('true')) log.info("getAsync GET to %s" % self.endpoint) return apiRequest(self, self.endpoint, "GET", returnResults=True) #eof