Source

slicehost-dynamic-dns / slicehost.py

Full commit
#!/usr/bin/env python

import cgi
import logging
import os
import re
import sys
import urlparse

from ConfigParser import RawConfigParser
from urllib2 import urlopen

from pyactiveresource.activeresource import ActiveResource


VERSION = (0, 1, 0)

__version__ = '.'.join(map(str, VERSION))
__author__ = 'Paul McLanahan'
__contact__ = 'paul@mclanahan.net'
__homepage__ = 'http://bitbucket.org/pmclanahan/slicehost-dynamic-dns'
__license__ = 'BSD (3 clause)'

__all__ = ['Slicehost']
BASE_URL = 'https://%s@api.slicehost.com/'
LOG_FILE = '/var/log/slicehost_ddns.log'
CONFIG_FILE = os.environ.get('SLICEHOST_CONFIG', '/etc/slicehost_ddns.conf')


class Zone(ActiveResource):

    def set_ip_for_records(self, ip_address, names=None, record_type='A'):
        if not names:
            names = [self.origin]

        elif isinstance(names, basestring):
            names = [names]

        records = Record.find(zone_id=self.id, record_type=record_type)
        r_count = 0
        for record in records:
            if record.name in names:
                record.data = ip_address
                record.save()
                r_count += 1

        return r_count


class Record(ActiveResource):
    pass


class Slicehost(object):

    def __init__(self, api_key):
        self.api_key = api_key
        site_url = BASE_URL % api_key
        Zone.site = site_url
        Record.site = site_url

    def set_zone_ip(self, domain, ip_address, names=None, record_type='A'):
        if not domain.endswith('.'):
            domain += '.'
        zone = Zone.find_first(origin=domain)
        if zone is None:
            return False
        return zone.set_ip_for_records(ip_address, names, record_type)

def main(cfg_file=CONFIG_FILE):
    logging.basicConfig(filename=LOG_FILE,
                        level=logging.INFO,
                        format='%(asctime)s %(levelname)s %(message)s')

    def print_result(message='success'):
        print "ContentType: text/plain\n"
        print message
        exit(0)
        
    if not os.path.exists(CONFIG_FILE):
        print_result('no config file')
    
    config = RawConfigParser({'names':None})
    config.read(cfg_file)
    try:
        html = urlopen('http://checkip.dyndns.org/').read()
    except IOError:
        print_result('error')
    m = re.search(r'(\d{1,3}\.){3}(\d{1,3})', html)
    if m:
        ip = m.group(0)
        key = config.get('slicehost', 'api_key')
        domain = config.get('slicehost', 'domain')
        names = config.get('slicehost', 'names')
        if names:
            names = names.split()
        logging.debug('ip=%s, domain=%s, names=%r, key=%s', ip, domain, names, key)
        sh = Slicehost(key)
        sh.set_zone_ip(domain, ip, names)
        logging.info('set %s to %s', domain, ip)
        print_result()
    
    print_result('error')

if __name__ == '__main__':
    main()