Skip to content

Instantly share code, notes, and snippets.

@bfleming-ciena
Forked from mariocesar/dyndns_route53.py
Created December 30, 2013 22:53
Show Gist options
  • Save bfleming-ciena/8189586 to your computer and use it in GitHub Desktop.
Save bfleming-ciena/8189586 to your computer and use it in GitHub Desktop.
"""
Requeriments:
$ sudo pip install boto dnspython
Edit ~/.boto to use your AWS credentials
"""
import time
import sys
import urllib2
import dns.resolver
from boto.route53.connection import Route53Connection
from boto.route53.exception import DNSServerError
from boto.route53.record import ResourceRecordSets
import logging
logger = logging.getLogger(__name__)
handler = logging.FileHandler('dyndns_route53.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
# Settings, Change me!
HOSTED_ZONE = 'ZXQU10000001'
DOMAIN_NAME = 'home.mydomain.com'
get_change_id = lambda response: response['ChangeInfo']['Id'].split('/')[-1]
get_change_status = lambda response: response['ChangeInfo']['Status']
def resolve_name_ip(name):
resolver = dns.resolver.Resolver()
resolver.nameservers = [
'8.8.8.8',
'8.8.4.4'
]
answer = resolver.query(name)
"""
>>> answer.response.answer[0].to_text()
home.mydomain.com. 60 IN A 192.168.0.2'
>>> answer.response.answer[0].items
[<DNS IN A rdata: 192.168.0.2>]
>>> answer.response.answer[0].items[0].address
'192.168.0.2'
"""
return answer.response.answer[0].items[0].address
def main():
# Get your ip using a public service
current_ip = urllib2.urlopen('http://ip.42.pl/raw').read()
# Avoid to hit the Route53 API if is not necessary.
# so compare first to a DNS server if the IP changed
resolved_ip = resolve_name_ip(DOMAIN_NAME)
if resolved_ip == current_ip:
logger.debug('DNS response (%s) and public IP (%s) are the same, nothing to do' % (resolved_ip, current_ip))
return
conn = Route53Connection()
try:
zone = conn.get_hosted_zone(HOSTED_ZONE)
except DNSServerError:
logger.error('%s Zone Not Found' % HOSTED_ZONE)
sys.exit(1)
response = conn.get_all_rrsets(HOSTED_ZONE, 'A', DOMAIN_NAME, maxitems=1)[0]
if current_ip not in response.resource_records:
logger.info('Found new IP: %s' % current_ip)
# Delete the old record, and create a new one.
# This code is from route53.py script, the change record command
changes = ResourceRecordSets(conn, HOSTED_ZONE, '')
change1 = changes.add_change("DELETE", DOMAIN_NAME, 'A', response.ttl)
for old_value in response.resource_records:
change1.add_value(old_value)
change2 = changes.add_change("CREATE", DOMAIN_NAME, 'A', response.ttl)
change2.add_value(current_ip)
try:
commit = changes.commit()
logger.debug('%s' % commit)
except:
logger.error("Changes can't be made: %s" % commit)
sys.exit(1)
else:
change = conn.get_change(get_change_id(commit['ChangeResourceRecordSetsResponse']))
logger.debug('%s' % change)
while get_change_status(change['GetChangeResponse']) == 'PENDING':
time.sleep(2)
change = conn.get_change(get_change_id(change['GetChangeResponse']))
logger.debug('%s' % change)
if get_change_status(change['GetChangeResponse']) == 'INSYNC':
logger.info('Change %s A de %s -> %s' % (DOMAIN_NAME, response.resource_records[0], current_ip))
else:
logger.warning('Unknow status for the change: %s' % change)
logger.debug('%s' % change)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment