Skip to content

Instantly share code, notes, and snippets.

@mariocesar
Created November 25, 2012 06:08
Show Gist options
  • Save mariocesar/4142563 to your computer and use it in GitHub Desktop.
Save mariocesar/4142563 to your computer and use it in GitHub Desktop.

Revisions

  1. mariocesar created this gist Nov 25, 2012.
    107 changes: 107 additions & 0 deletions dyndns_route53.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,107 @@
    """
    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()