| OLD | NEW |
| 1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ | 1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ |
| 2 # Copyright (c) 2010, Eucalyptus Systems, Inc. | 2 # Copyright (c) 2010, Eucalyptus Systems, Inc. |
| 3 # | 3 # |
| 4 # Permission is hereby granted, free of charge, to any person obtaining a | 4 # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 # copy of this software and associated documentation files (the | 5 # copy of this software and associated documentation files (the |
| 6 # "Software"), to deal in the Software without restriction, including | 6 # "Software"), to deal in the Software without restriction, including |
| 7 # without limitation the rights to use, copy, modify, merge, publish, dis- | 7 # without limitation the rights to use, copy, modify, merge, publish, dis- |
| 8 # tribute, sublicense, and/or sell copies of the Software, and to permit | 8 # tribute, sublicense, and/or sell copies of the Software, and to permit |
| 9 # persons to whom the Software is furnished to do so, subject to the fol- | 9 # persons to whom the Software is furnished to do so, subject to the fol- |
| 10 # lowing conditions: | 10 # lowing conditions: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 <Name>%(name)s</Name> | 38 <Name>%(name)s</Name> |
| 39 <CallerReference>%(caller_ref)s</CallerReference> | 39 <CallerReference>%(caller_ref)s</CallerReference> |
| 40 <HostedZoneConfig> | 40 <HostedZoneConfig> |
| 41 <Comment>%(comment)s</Comment> | 41 <Comment>%(comment)s</Comment> |
| 42 </HostedZoneConfig> | 42 </HostedZoneConfig> |
| 43 </CreateHostedZoneRequest>""" | 43 </CreateHostedZoneRequest>""" |
| 44 | 44 |
| 45 #boto.set_stream_logger('dns') | 45 #boto.set_stream_logger('dns') |
| 46 | 46 |
| 47 class Route53Connection(AWSAuthConnection): | 47 class Route53Connection(AWSAuthConnection): |
| 48 DefaultHost = 'route53.amazonaws.com' |
| 49 """The default Route53 API endpoint to connect to.""" |
| 48 | 50 |
| 49 DefaultHost = 'route53.amazonaws.com' | 51 Version = '2011-05-05' |
| 50 Version = '2010-10-01' | 52 """Route53 API version.""" |
| 51 XMLNameSpace = 'https://route53.amazonaws.com/doc/2010-10-01/' | 53 |
| 54 XMLNameSpace = 'https://route53.amazonaws.com/doc/2011-05-05/' |
| 55 """XML schema for this Route53 API version.""" |
| 52 | 56 |
| 53 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, | 57 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, |
| 54 port=None, proxy=None, proxy_port=None, | 58 port=None, proxy=None, proxy_port=None, |
| 55 host=DefaultHost, debug=0): | 59 host=DefaultHost, debug=0): |
| 56 AWSAuthConnection.__init__(self, host, | 60 AWSAuthConnection.__init__(self, host, |
| 57 aws_access_key_id, aws_secret_access_key, | 61 aws_access_key_id, aws_secret_access_key, |
| 58 True, port, proxy, proxy_port, debug=debug) | 62 True, port, proxy, proxy_port, debug=debug) |
| 59 | 63 |
| 60 def _required_auth_capability(self): | 64 def _required_auth_capability(self): |
| 61 return ['route53'] | 65 return ['route53'] |
| 62 | 66 |
| 63 def make_request(self, action, path, headers=None, data='', params=None): | 67 def make_request(self, action, path, headers=None, data='', params=None): |
| 64 if params: | 68 if params: |
| 65 pairs = [] | 69 pairs = [] |
| 66 for key, val in params.iteritems(): | 70 for key, val in params.iteritems(): |
| 67 if val is None: continue | 71 if val is None: continue |
| 68 pairs.append(key + '=' + urllib.quote(str(val))) | 72 pairs.append(key + '=' + urllib.quote(str(val))) |
| 69 path += '?' + '&'.join(pairs) | 73 path += '?' + '&'.join(pairs) |
| 70 return AWSAuthConnection.make_request(self, action, path, headers, data) | 74 return AWSAuthConnection.make_request(self, action, path, headers, data) |
| 71 | 75 |
| 72 # Hosted Zones | 76 # Hosted Zones |
| 73 | 77 |
| 74 def get_all_hosted_zones(self): | 78 def get_all_hosted_zones(self, start_marker=None, zone_list=None): |
| 75 """ | 79 """ |
| 76 Returns a Python data structure with information about all | 80 Returns a Python data structure with information about all |
| 77 Hosted Zones defined for the AWS account. | 81 Hosted Zones defined for the AWS account. |
| 82 |
| 83 :param int start_marker: start marker to pass when fetching additional |
| 84 results after a truncated list |
| 85 :param list zone_list: a HostedZones list to prepend to results |
| 78 """ | 86 """ |
| 79 response = self.make_request('GET', '/%s/hostedzone' % self.Version) | 87 params = {} |
| 88 if start_marker: |
| 89 params = {'marker': start_marker} |
| 90 response = self.make_request('GET', '/%s/hostedzone' % self.Version, |
| 91 params=params) |
| 80 body = response.read() | 92 body = response.read() |
| 81 boto.log.debug(body) | 93 boto.log.debug(body) |
| 82 if response.status >= 300: | 94 if response.status >= 300: |
| 83 raise exception.DNSServerError(response.status, | 95 raise exception.DNSServerError(response.status, |
| 84 response.reason, | 96 response.reason, |
| 85 body) | 97 body) |
| 86 e = boto.jsonresponse.Element(list_marker='HostedZones', | 98 e = boto.jsonresponse.Element(list_marker='HostedZones', |
| 87 item_marker=('HostedZone',)) | 99 item_marker=('HostedZone',)) |
| 88 h = boto.jsonresponse.XmlHandler(e, None) | 100 h = boto.jsonresponse.XmlHandler(e, None) |
| 89 h.parse(body) | 101 h.parse(body) |
| 102 if zone_list: |
| 103 e['ListHostedZonesResponse']['HostedZones'].extend(zone_list) |
| 104 while e['ListHostedZonesResponse'].has_key('NextMarker'): |
| 105 next_marker = e['ListHostedZonesResponse']['NextMarker'] |
| 106 zone_list = e['ListHostedZonesResponse']['HostedZones'] |
| 107 e = self.get_all_hosted_zones(next_marker, zone_list) |
| 90 return e | 108 return e |
| 91 | 109 |
| 92 def get_hosted_zone(self, hosted_zone_id): | 110 def get_hosted_zone(self, hosted_zone_id): |
| 93 """ | 111 """ |
| 94 Get detailed information about a particular Hosted Zone. | 112 Get detailed information about a particular Hosted Zone. |
| 95 | 113 |
| 96 :type hosted_zone_id: str | 114 :type hosted_zone_id: str |
| 97 :param hosted_zone_id: The unique identifier for the Hosted Zone | 115 :param hosted_zone_id: The unique identifier for the Hosted Zone |
| 98 | 116 |
| 99 """ | 117 """ |
| 100 uri = '/%s/hostedzone/%s' % (self.Version, hosted_zone_id) | 118 uri = '/%s/hostedzone/%s' % (self.Version, hosted_zone_id) |
| 101 response = self.make_request('GET', uri) | 119 response = self.make_request('GET', uri) |
| 102 body = response.read() | 120 body = response.read() |
| 103 boto.log.debug(body) | 121 boto.log.debug(body) |
| 104 if response.status >= 300: | 122 if response.status >= 300: |
| 105 raise exception.DNSServerError(response.status, | 123 raise exception.DNSServerError(response.status, |
| 106 response.reason, | 124 response.reason, |
| 107 body) | 125 body) |
| 108 e = boto.jsonresponse.Element(list_marker='NameServers', | 126 e = boto.jsonresponse.Element(list_marker='NameServers', |
| 109 item_marker=('NameServer',)) | 127 item_marker=('NameServer',)) |
| 110 h = boto.jsonresponse.XmlHandler(e, None) | 128 h = boto.jsonresponse.XmlHandler(e, None) |
| 111 h.parse(body) | 129 h.parse(body) |
| 112 return e | 130 return e |
| 113 | 131 |
| 114 def create_hosted_zone(self, domain_name, caller_ref=None, comment=''): | 132 def create_hosted_zone(self, domain_name, caller_ref=None, comment=''): |
| 115 """ | 133 """ |
| 116 Create a new Hosted Zone. Returns a Python data structure with | 134 Create a new Hosted Zone. Returns a Python data structure with |
| 117 information about the newly created Hosted Zone. | 135 information about the newly created Hosted Zone. |
| 118 | 136 |
| 119 :type domain_name: str | 137 :type domain_name: str |
| 120 :param domain_name: The name of the domain. This should be a | 138 :param domain_name: The name of the domain. This should be a |
| 121 fully-specified domain, and should end with | 139 fully-specified domain, and should end with a final period |
| 122 a final period as the last label indication. | 140 as the last label indication. If you omit the final period, |
| 123 If you omit the final period, Amazon Route 53 | 141 Amazon Route 53 assumes the domain is relative to the root. |
| 124 assumes the domain is relative to the root. | 142 This is the name you have registered with your DNS registrar. |
| 125 This is the name you have registered with your | 143 It is also the name you will delegate from your registrar to |
| 126 DNS registrar. It is also the name you will | 144 the Amazon Route 53 delegation servers returned in |
| 127 delegate from your registrar to the Amazon | 145 response to this request.A list of strings with the image |
| 128 Route 53 delegation servers returned in | 146 IDs wanted. |
| 129 response to this request.A list of strings | |
| 130 with the image IDs wanted | |
| 131 | 147 |
| 132 :type caller_ref: str | 148 :type caller_ref: str |
| 133 :param caller_ref: A unique string that identifies the request | 149 :param caller_ref: A unique string that identifies the request |
| 134 and that allows failed CreateHostedZone requests | 150 and that allows failed CreateHostedZone requests to be retried |
| 135 to be retried without the risk of executing the | 151 without the risk of executing the operation twice. If you don't |
| 136 operation twice. | 152 provide a value for this, boto will generate a Type 4 UUID and |
| 137 If you don't provide a value for this, boto will | 153 use that. |
| 138 generate a Type 4 UUID and use that. | |
| 139 | 154 |
| 140 :type comment: str | 155 :type comment: str |
| 141 :param comment: Any comments you want to include about the hosted | 156 :param comment: Any comments you want to include about the hosted |
| 142 zone. | 157 zone. |
| 143 | 158 |
| 144 """ | 159 """ |
| 145 if caller_ref is None: | 160 if caller_ref is None: |
| 146 caller_ref = str(uuid.uuid4()) | 161 caller_ref = str(uuid.uuid4()) |
| 147 params = {'name' : domain_name, | 162 params = {'name' : domain_name, |
| 148 'caller_ref' : caller_ref, | 163 'caller_ref' : caller_ref, |
| 149 'comment' : comment, | 164 'comment' : comment, |
| 150 'xmlns' : self.XMLNameSpace} | 165 'xmlns' : self.XMLNameSpace} |
| 151 xml = HZXML % params | 166 xml = HZXML % params |
| 152 uri = '/%s/hostedzone' % self.Version | 167 uri = '/%s/hostedzone' % self.Version |
| (...skipping 22 matching lines...) Expand all Loading... |
| 175 response.reason, | 190 response.reason, |
| 176 body) | 191 body) |
| 177 e = boto.jsonresponse.Element() | 192 e = boto.jsonresponse.Element() |
| 178 h = boto.jsonresponse.XmlHandler(e, None) | 193 h = boto.jsonresponse.XmlHandler(e, None) |
| 179 h.parse(body) | 194 h.parse(body) |
| 180 return e | 195 return e |
| 181 | 196 |
| 182 # Resource Record Sets | 197 # Resource Record Sets |
| 183 | 198 |
| 184 def get_all_rrsets(self, hosted_zone_id, type=None, | 199 def get_all_rrsets(self, hosted_zone_id, type=None, |
| 185 name=None, maxitems=None): | 200 name=None, identifier=None, maxitems=None): |
| 186 """ | 201 """ |
| 187 Retrieve the Resource Record Sets defined for this Hosted Zone. | 202 Retrieve the Resource Record Sets defined for this Hosted Zone. |
| 188 Returns the raw XML data returned by the Route53 call. | 203 Returns the raw XML data returned by the Route53 call. |
| 189 | 204 |
| 190 :type hosted_zone_id: str | 205 :type hosted_zone_id: str |
| 191 :param hosted_zone_id: The unique identifier for the Hosted Zone | 206 :param hosted_zone_id: The unique identifier for the Hosted Zone |
| 192 | 207 |
| 193 :type type: str | 208 :type type: str |
| 194 :param type: The type of resource record set to begin the record | 209 :param type: The type of resource record set to begin the record |
| 195 listing from. Valid choices are: | 210 listing from. Valid choices are: |
| 196 | 211 |
| 197 * A | 212 * A |
| 198 * AAAA | 213 * AAAA |
| 199 * CNAME | 214 * CNAME |
| 200 * MX | 215 * MX |
| 201 * NS | 216 * NS |
| 202 * PTR | 217 * PTR |
| 203 * SOA | 218 * SOA |
| 204 * SPF | 219 * SPF |
| 205 * SRV | 220 * SRV |
| 206 * TXT | 221 * TXT |
| 222 |
| 223 Valid values for weighted resource record sets: |
| 224 |
| 225 * A |
| 226 * AAAA |
| 227 * CNAME |
| 228 * TXT |
| 229 |
| 230 Valid values for Zone Apex Aliases: |
| 231 |
| 232 * A |
| 233 * AAAA |
| 207 | 234 |
| 208 :type name: str | 235 :type name: str |
| 209 :param name: The first name in the lexicographic ordering of domain | 236 :param name: The first name in the lexicographic ordering of domain |
| 210 names to be retrieved | 237 names to be retrieved |
| 211 | 238 |
| 239 :type identifier: str |
| 240 :param identifier: In a hosted zone that includes weighted resource |
| 241 record sets (multiple resource record sets with the same DNS |
| 242 name and type that are differentiated only by SetIdentifier), |
| 243 if results were truncated for a given DNS name and type, |
| 244 the value of SetIdentifier for the next resource record |
| 245 set that has the current DNS name and type |
| 246 |
| 212 :type maxitems: int | 247 :type maxitems: int |
| 213 :param maxitems: The maximum number of records | 248 :param maxitems: The maximum number of records |
| 214 | 249 |
| 215 """ | 250 """ |
| 216 from boto.route53.record import ResourceRecordSets | 251 from boto.route53.record import ResourceRecordSets |
| 217 params = {'type': type, 'name': name, 'maxitems': maxitems} | 252 params = {'type': type, 'name': name, |
| 253 'Identifier': identifier, 'maxitems': maxitems} |
| 218 uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) | 254 uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) |
| 219 response = self.make_request('GET', uri, params=params) | 255 response = self.make_request('GET', uri, params=params) |
| 220 body = response.read() | 256 body = response.read() |
| 221 boto.log.debug(body) | 257 boto.log.debug(body) |
| 222 if response.status >= 300: | 258 if response.status >= 300: |
| 223 raise exception.DNSServerError(response.status, | 259 raise exception.DNSServerError(response.status, |
| 224 response.reason, | 260 response.reason, |
| 225 body) | 261 body) |
| 226 rs = ResourceRecordSets(connection=self, hosted_zone_id=hosted_zone_id) | 262 rs = ResourceRecordSets(connection=self, hosted_zone_id=hosted_zone_id) |
| 227 h = handler.XmlHandler(rs, self) | 263 h = handler.XmlHandler(rs, self) |
| 228 xml.sax.parseString(body, h) | 264 xml.sax.parseString(body, h) |
| 229 return rs | 265 return rs |
| 230 | 266 |
| 231 def change_rrsets(self, hosted_zone_id, xml_body): | 267 def change_rrsets(self, hosted_zone_id, xml_body): |
| 232 """ | 268 """ |
| 233 Create or change the authoritative DNS information for this | 269 Create or change the authoritative DNS information for this |
| 234 Hosted Zone. | 270 Hosted Zone. |
| 235 Returns a Python data structure with information about the set of | 271 Returns a Python data structure with information about the set of |
| 236 changes, including the Change ID. | 272 changes, including the Change ID. |
| 237 | 273 |
| 238 :type hosted_zone_id: str | 274 :type hosted_zone_id: str |
| 239 :param hosted_zone_id: The unique identifier for the Hosted Zone | 275 :param hosted_zone_id: The unique identifier for the Hosted Zone |
| 240 | 276 |
| 241 :type xml_body: str | 277 :type xml_body: str |
| 242 :param xml_body: The list of changes to be made, defined in the | 278 :param xml_body: The list of changes to be made, defined in the |
| 243 XML schema defined by the Route53 service. | 279 XML schema defined by the Route53 service. |
| 244 | 280 |
| 245 """ | 281 """ |
| 246 uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) | 282 uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) |
| 247 response = self.make_request('POST', uri, | 283 response = self.make_request('POST', uri, |
| 248 {'Content-Type' : 'text/xml'}, | 284 {'Content-Type' : 'text/xml'}, |
| 249 xml_body) | 285 xml_body) |
| 250 body = response.read() | 286 body = response.read() |
| 251 boto.log.debug(body) | 287 boto.log.debug(body) |
| 252 if response.status >= 300: | 288 if response.status >= 300: |
| 253 raise exception.DNSServerError(response.status, | 289 raise exception.DNSServerError(response.status, |
| 254 response.reason, | 290 response.reason, |
| 255 body) | 291 body) |
| 256 e = boto.jsonresponse.Element() | 292 e = boto.jsonresponse.Element() |
| 257 h = boto.jsonresponse.XmlHandler(e, None) | 293 h = boto.jsonresponse.XmlHandler(e, None) |
| 258 h.parse(body) | 294 h.parse(body) |
| 259 return e | 295 return e |
| 260 | 296 |
| 261 def get_change(self, change_id): | 297 def get_change(self, change_id): |
| 262 """ | 298 """ |
| 263 Get information about a proposed set of changes, as submitted | 299 Get information about a proposed set of changes, as submitted |
| 264 by the change_rrsets method. | 300 by the change_rrsets method. |
| 265 Returns a Python data structure with status information about the | 301 Returns a Python data structure with status information about the |
| 266 changes. | 302 changes. |
| 267 | 303 |
| 268 :type change_id: str | 304 :type change_id: str |
| 269 :param change_id: The unique identifier for the set of changes. | 305 :param change_id: The unique identifier for the set of changes. |
| 270 This ID is returned in the response to the | 306 This ID is returned in the response to the change_rrsets method. |
| 271 change_rrsets method. | |
| 272 | 307 |
| 273 """ | 308 """ |
| 274 uri = '/%s/change/%s' % (self.Version, change_id) | 309 uri = '/%s/change/%s' % (self.Version, change_id) |
| 275 response = self.make_request('GET', uri) | 310 response = self.make_request('GET', uri) |
| 276 body = response.read() | 311 body = response.read() |
| 277 boto.log.debug(body) | 312 boto.log.debug(body) |
| 278 if response.status >= 300: | 313 if response.status >= 300: |
| 279 raise exception.DNSServerError(response.status, | 314 raise exception.DNSServerError(response.status, |
| 280 response.reason, | 315 response.reason, |
| 281 body) | 316 body) |
| 282 e = boto.jsonresponse.Element() | 317 e = boto.jsonresponse.Element() |
| 283 h = boto.jsonresponse.XmlHandler(e, None) | 318 h = boto.jsonresponse.XmlHandler(e, None) |
| 284 h.parse(body) | 319 h.parse(body) |
| 285 return e | 320 return e |
| OLD | NEW |