示例#1
0
    def from_cli_options(cls, domains, access_key_id, access_key_secret, type):
        """
        Construct a Config object from a set of given configurations

        Args:
            domains: domains to update
            access_key_id: access key id provided by api provider
            access_key_secret: access key secret provided by api provider
            type: dns record type, for now only 'A' is supported
        Returns: 
            Instance of Config
        """
        if not domains or not access_key_id or not access_key_secret:
            DDNSUtils.err_and_exit("Aruguments are not sufficient: domains, access_key_id and access_key_secret")
        
        apiProviderInfo = ApiProviderInfo(access_key_id, access_key_secret)

        records = []
        try:
            for fullDomain in domains:
                record = DomainSection.from_full_domain(fullDomain, type)
                records.append(record)
            config = cls(apiProviderInfo, records)
            return config
        except ValueError as ex:
            DDNSUtils.err_and_exit("Invalid parameters in config: {0}".format(ex))
示例#2
0
    def __init__(self):
        # default options
        self.debug = False
        self.interval = 600
        self.access_id = None
        self.access_key = None

        self.parser = ConfigParser.ConfigParser()
        if not self.parser.read(CONF_FILE):
            # Compaitible consideration for v0.1
            if not self.parser.read(SYS_CONF_FILE):
                DDNSUtils.err_and_exit("Failed to read config file.")

        try:
            self.debug = self.parser.getboolean("DEFAULT", "debug")
            self.access_id = self.parser.get("DEFAULT", "access_id")
            self.access_key = self.parser.get("DEFAULT", "access_key")
        except ValueError as ex:
            DDNSUtils.err_and_exit("Invalid debug in config: {0}".format(ex))
        except ConfigParser.NoSectionError as ex:
            DDNSUtils.err_and_exit("Invalid config: {0}".format(ex))
        except ConfigParser.NoOptionError as ex:
            DDNSUtils.err_and_exit("Invalid config: {0}".format(ex))

        if not self.access_id or not self.access_key:
            DDNSUtils.err_and_exit(
                "Invalid access_id or access_key in config file.")
示例#3
0
def main():
    """
    Main routine
    """
    config = DDNSConfig()
    record_manager = DDNSDomainRecordManager(config)

    # get current public ip for this server
    if config.pifn_enable:
        current_public_ip = DDNSUtils.get_interface_address(
            config.pifn_interface)
    else:
        current_public_ip = DDNSUtils.get_current_public_ip()
    if not current_public_ip:
        DDNSUtils.err_and_exit("Failed to get current public IP")

    for local_record in record_manager.local_record_list:
        if local_record.subdomain == '*':
            dns_resolved_ip = DDNSUtils.get_dns_resolved_ip(
                'xxx', local_record.domainname)
        else:
            dns_resolved_ip = DDNSUtils.get_dns_resolved_ip(
                local_record.subdomain, local_record.domainname)

        if local_record.type == "AAAA":
            current_ip = DDNSUtils.get_interface_ipv6_address(
                local_record.interface)
        else:
            current_ip = current_public_ip

        if current_ip == dns_resolved_ip:
            DDNSUtils.info("Skipped as no changes for DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        # If current public IP doesn't equal to current DNS resolved ip, only in three cases:
        # 1. The new synced IP for remote record in Aliyun doesn't take effect yet
        # 2. remote record's IP in Aliyun server has changed
        # 3. current public IP is changed
        remote_record = record_manager.fetch_remote_record(local_record)
        if not remote_record:
            DDNSUtils.err("Failed finding remote DomainRecord" \
                          "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        if current_ip == remote_record.value:
            DDNSUtils.info("Skipped as we already updated DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        # if we can fetch remote record and record's value doesn't equal to public IP
        sync_result = record_manager.update(remote_record, current_ip,
                                            local_record.type)

        if not sync_result:
            DDNSUtils.err("Failed updating DomainRecord" \
                          "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
        else:
            DDNSUtils.info("Successfully updated DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
示例#4
0
    def validate(self):
        if not self.accessId or not self.accessKey:
            DDNSUtils.err_and_exit("Invalid access_id or access_key in config file.")

        for rec in self.localDomainRecordList:
            if not rec.domain or not rec.subDomain or not rec.type:
                DDNSUtils.err_and_exit("Invalid domain or sub_domain or type in config file.")
示例#5
0
    def validate(self):
        if not self.accessId or not self.accessKey:
            DDNSUtils.err_and_exit(
                "Invalid access_id or access_key in config file.")

        for rec in self.localDomainRecordList:
            if not rec.domain or not rec.subDomain or not rec.type:
                DDNSUtils.err_and_exit(
                    "Invalid domain or sub_domain or type in config file.")
示例#6
0
def main(method, *args):
    """
    Main routine
    """
    config = DDNSConfig()
    record_manager = DDNSDomainRecordManager(config)

    # get current public ip for this server
    def switch(m):
        switcher = {
            "net": lambda: DDNSUtils.get_current_public_ip(),
            "static": lambda: args[0],
        }
        return switcher.get(m, lambda: "net|static 10.0.0.1")

    func = switch(method)
    current_public_ip = func()

    if not current_public_ip:
        DDNSUtils.err_and_exit("Failed to get current public IP")

    for local_record in record_manager.local_record_list:
        dns_resolved_ip = DDNSUtils.get_dns_resolved_ip(local_record.subdomain,
                                                        local_record.domainname)

        if current_public_ip == dns_resolved_ip:
            DDNSUtils.info("Skipped as no changes for DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        # If current public IP doesn't equal to current DNS resolved ip, only in three cases:
        # 1. The new synced IP for remote record in Aliyun doesn't take effect yet
        # 2. remote record's IP in Aliyun server has changed
        # 3. current public IP is changed
        remote_record = record_manager.fetch_remote_record(local_record)
        if not remote_record:
            DDNSUtils.err("Failed finding remote DomainRecord" \
                          "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        if current_public_ip == remote_record.value:
            DDNSUtils.info("Skipped as we already updated DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        # if we can fetch remote record and record's value doesn't equal to public IP
        sync_result = record_manager.update(remote_record, current_public_ip)
        if not sync_result:
            DDNSUtils.err("Failed updating DomainRecord" \
                          "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
        else:
            DDNSUtils.info("Successfully updated DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
示例#7
0
    def perform_ddns(self):
        """
        Perform the ddns process when everything is ready
        """
        current_public_ip = DDNSUtils.get_current_public_ip()

        if not current_public_ip:
            DDNSUtils.err_and_exit("Failed to get local public IP")

        DDNSUtils.info(
            "Local public ip address read: [{0}]".format(current_public_ip))

        for record_to_update in self.configuration.recordsToUpdate:
            dns_resolved_ip = record_to_update.get_dns_resolved_ip()

            if current_public_ip == dns_resolved_ip:
                DDNSUtils.info(
                    "Skipped as no changes for DomainRecord: [{rec.subDomainName}.{rec.domainName}]"
                    .format(rec=record_to_update))
                continue

            # If current public IP doesn't equal to current DNS resolved ip, only in three cases:
            # 1. The new synchronized IP for remote record in api provider doesn't take effect yet
            # 2. remote record's IP in Aliyun server has changed
            # 3. current public IP is changed
            dns_record = self.get_dns_record(record_to_update)
            if not dns_record:
                DDNSUtils.err(
                    "Failed to get dns resolution record for [{rec.subDomainName}.{rec.domainName}]"
                    .format(rec=record_to_update))
                continue

            if current_public_ip == dns_record.value:
                DDNSUtils.info(
                    "Skipped: dns record already updated: [{rec.subDomainName}.{rec.domainName}]"
                    .format(rec=record_to_update))
                continue

            dns_record.value = current_public_ip
            result = self.update_dns_record(dns_record, current_public_ip)
            if not result:
                DDNSUtils.err(
                    "Failed to update dns record: [{rec.subDomainName}.{rec.domainName}]"
                    .format(rec=record_to_update))
            else:
                DDNSUtils.info(
                    "Successfully update dns record: [{rec.subDomainName}.{rec.domainName}]"
                    .format(rec=record_to_update))
示例#8
0
def main():
    """
    Main routine
    """
    config = DDNSConfig()
    record_manager = DDNSDomainRecordManager(config)

    # get current public ip for this server
    current_public_ip = DDNSUtils.get_current_public_ip()
    if not current_public_ip:
        DDNSUtils.err_and_exit("Failed to get current public IP")

    for local_record in record_manager.local_record_list:
        dns_resolved_ip = DDNSUtils.get_dns_resolved_ip(local_record.subdomain,
                                                        local_record.domainname)

        if current_public_ip == dns_resolved_ip:
            DDNSUtils.info("Skipped as no changes for DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        # If current public IP doesn't equal to current DNS resolved ip, only in three cases:
        # 1. The new synced IP for remote record in Aliyun doesn't take effect yet
        # 2. remote record's IP in Aliyun server has changed
        # 3. current public IP is changed
        remote_record = record_manager.fetch_remote_record(local_record)
        if not remote_record:
            DDNSUtils.err("Failed finding remote DomainRecord" \
                          "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        if current_public_ip == remote_record.value:
            DDNSUtils.info("Skipped as we already updated DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
            continue

        # if we can fetch remote record and record's value doesn't equal to public IP
        sync_result = record_manager.update(remote_record, current_public_ip)
        if not sync_result:
            DDNSUtils.err("Failed updating DomainRecord" \
                          "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
        else:
            DDNSUtils.info("Successfully updated DomainRecord" \
                           "[{rec.subdomain}.{rec.domainname}]".format(rec=local_record))
示例#9
0
    def get_feature_public_ip_from_nic_options(self):
        """
        Get options about the getting ip from nic.
        """
        section_name = "feature_public_ip_from_nic"
        try:
            enable = self.parser.getboolean(section_name, "enable")
        except ValueError as ex:
            DDNSUtils.err_and_exit(
                "Invalid 'enable' value in feature public_ip_from_nic config: {0}"
                .format(ex))
        except ConfigParser.NoOptionError as ex:
            enable = False

        self.pifn_enable = enable
        if enable:
            try:
                self.pifn_interface = self.parser.get(section_name,
                                                      "interface")
            except ConfigParser.NoOptionError as ex:
                DDNSUtils.err_and_exit("No interface specified")

            if self.pifn_interface == "":
                DDNSUtils.err_and_exit("Empty interface")
示例#10
0
    def from_config_file(cls, configFilePath):
        """
        Construct a Config object from a given config file

        Args:
            configFilePath: path to the given config file
        Returns: 
            Instance of Config
        """
        parser = ConfigParser()
        if not parser.read(configFilePath):
            DDNSUtils.err_and_exit("Failed to read config file.")

        try:
            access_key_id = parser.get("ApiProvider", "access_key_id")
            access_key_secret = parser.get("ApiProvider", "access_key_secret")
            
            if not access_key_id or not access_key_secret:
                DDNSUtils.err_and_exit("Invalid access_id or access_key in config file.")
            apiProviderInfo = ApiProviderInfo(access_key_id, access_key_secret)

            DDNSUtils.info("Read Access Key Id: [{0}]".format(access_key_id))
            DDNSUtils.info("Read Access Key Secret: [{0}]".format(access_key_secret))

            recordsSections = [s for s in parser.sections() if s.startswith("DomainNameToUpdate") ]

            records = []
            for record in recordsSections:
                domain = parser.get(record,'domain')
                type = parser.get(record,'type')
                subDomains = parser.get(record,'sub_domain').split(',')
                if not domain or not type or not subDomains:
                    DDNSUtils.err_and_exit("Invalid domian record.")
                
                DDNSUtils.info("Read Domain: [{0}]".format(domain))
                DDNSUtils.info("Read Sub Domains: [{0}]".format(subDomains))
                DDNSUtils.info("Read Type: [{0}]".format(type))

                for subDomain in subDomains:
                    record = DomainSection(domain, subDomain.strip(), type)
                    records.append(record)
            config = cls(apiProviderInfo, records)
            return config

        except ValueError as ex:
            DDNSUtils.err_and_exit("Invalid debug in config: {0}".format(ex))
        except NoSectionError as ex:
            DDNSUtils.err_and_exit("Invalid config: {0}".format(ex))
        except NoOptionError as ex:
            DDNSUtils.err_and_exit("Invalid config: {0}".format(ex))
示例#11
0
from utils import DDNSUtils
from config import DDNSConfig

CONF_FILE = "/etc/ddns.conf"

if __name__ == "__main__":
    config = DDNSConfig(CONF_FILE)
    config.validate()

    utils = DDNSUtils(config.debug)
    helper = DDNSHelper(config)

    # get current public ip
    currentPublicIP = utils.getCurrentPublicIP()
    if not currentPublicIP:
        DDNSUtils.err_and_exit("Failed to get current public ip")

    for localRecord in config.localDomainRecordList:
        # if we don't have domain record's id in config file, then we never sync to server before
        if not localRecord.id or not localRecord.value:
            result = helper.syncFirstTime(localRecord, currentPublicIP)
            if result is False:
                DDNSUtils.err_and_exit(
                    "Failed doing the first time sync for record:{0}".format(
                        localRecord.alias))
                continue

            DDNSUtils.info("Successfully sync done for record:{0}".format(
                localRecord.alias))
            continue
示例#12
0
from utils import DDNSUtils
from config import DDNSConfig

CONF_FILE = "/etc/ddns.conf"

if __name__ == "__main__":
    config = DDNSConfig(CONF_FILE)
    config.validate()

    utils = DDNSUtils(config.debug)
    helper = DDNSHelper(config)

    # get current public ip
    currentPublicIP = utils.getCurrentPublicIP()
    if not currentPublicIP:
        DDNSUtils.err_and_exit("Failed to get current public ip")

    for localRecord in config.localDomainRecordList:
        # if we don't have domain record's id in config file, then we never sync to server before
        if not localRecord.id or not localRecord.value:
            result = helper.syncFirstTime(localRecord,currentPublicIP)
            if result is False:
                DDNSUtils.err_and_exit("Failed doing the first time sync for record:{0}".format(localRecord.alias))
                continue

            DDNSUtils.info("Successfully sync done for record:{0}".format(localRecord.alias))
            continue

        # if current public ip is not the same as the one in server
        if currentPublicIP != localRecord.value:
            if config.debug:
示例#13
0
    "--access-key-secret",
    '-k',
    help='The access key secret assigned by ddns api provider.')
argParser.add_argument(
    "--config",
    '-c',
    help=
    'The configuration file to refer to for ddns process. If this option is set, all other options will be ignored.'
)

args = argParser.parse_args()

if args.config:
    CONFIG_FILE_PATH = args.config
    if not os.path.exists(CONFIG_FILE_PATH):
        DDNSUtils.err_and_exit('File not found: {0}'.format(CONFIG_FILE_PATH))

    DDNSUtils.info(
        "Loading configuration from file: {0}".format(CONFIG_FILE_PATH))
    config = Config.from_config_file(CONFIG_FILE_PATH)
    coordinator = DDNSCoordinator(config)
    coordinator.perform_ddns()
    pass
elif not args.domains or not args.access_key_id or not args.access_key_secret:
    argParser.print_help()
else:
    DDNSUtils.info("Loading configuration from arguments.")
    config = Config.from_cli_options(args.domains, args.access_key_id,
                                     args.access_key_secret, args.type)
    coordinator = DDNSCoordinator(config)
    coordinator.perform_ddns()