def main(): # initialize mappings for the replacement fields in the templates mappings = parms('ddns_config.yaml') mappings.add('key_name', 'cloud.ddns') mappings.add('secret_key', get_ddns_key()) # initialize content named = content('templates/template.named.conf.local') options = content('templates/template.named.conf.options') forward_zone = content('templates/template.forward.cloudzone') reverse_zone = {} for net in mappings.value('ip_ranges'): reverse_zone[net] = content('templates/template.reverse.cloudzone') resolvconf = content('templates/template.resolv.conf') # create content for {forward_ips} mapping in named.conf text = "" for ip in mappings.value('forwarders'): text += "%s; " % ip mappings.add('forward_ips', text) # create content for {reverse_zones} mapping in named.conf rz_fields = "" zone_template = content('templates/template.named.zone') rz_dict = {} rz_dict['key_name'] = mappings.value('key_name') for net in mappings.value('ip_ranges'): text = zone_template.text rz_dict['revzone'] = reverse_dns_zone(net) rz_dict['revzone_file'] = revzone_filename(net) rz_fields += "%s\n" % text.format(**rz_dict) mappings.add('reverse_zones', rz_fields) # swap replacement fields with mapped content and add reverse lookup for the DNS instance IPs named.replace_fields(mappings) options.replace_fields(mappings) forward_zone.replace_fields(mappings) for net in mappings.value('ip_ranges'): reverse_zone[net].replace_fields(mappings) # add reverse lookup for the DNS instance for ip in [ mappings.value('dns_fixed_ip'), mappings.value('dns_floating_ip') ]: if netaddr.IPAddress(ip) in netaddr.IPNetwork(net): text = "%s IN A %s" % (mappings.value('dns_shortname'), ip) reverse_zone[net].append(text) resolvconf.replace_fields(mappings) # write content named.write('gen4bind/named.conf.local') options.write('gen4bind/named.conf.options') forward_zone.write('gen4bind/forward.cloudzone') for net in mappings.value('ip_ranges'): filename = "gen4bind/%s" % revzone_filename(net) reverse_zone[net].write(filename) resolvconf.write('gen4bind/resolv.conf')
#!/usr/bin/env python import os # miscellaneous operating system interfaces import sys # system paramteters from ddns_common import parms from ddns_common import file_suffix from ddns_common import get_ddns_key # initialize template/dictionary variables mappings = parms('ddns_config.yaml') key_name = 'cloud.ddns' key_value = get_ddns_key() text = "#!/bin/sh\n" text += "source ./openrc.sh\n" text += "python ddns.py\n" text += "nsupdate -y %s:%s -v %s\n" % (key_name, key_value, 'A_records') for net in mappings.value('ip_ranges'): filename = "PTR_%s" % file_suffix(net) text += "nsupdate -y %s:%s -v %s\n" % (key_name, key_value, filename) text += "rm A_records PTR_*" f = open('ddns.sh', 'w') f.write(text) f.close()
def main(): # Authenticate Credentials try: creds = get_nova_creds() except: print 'Please set OpenStack credentials, e.g. type source openrc.sh, and try again' sys.exit() # Retrieve the Nova client nova = novaclient.Client(**creds) # get template/dictionary variables mappings = parms('ddns_config.yaml') domain_name = mappings.value('domain_name') dns_name = mappings.value('dns_shortname') + "." + domain_name # initialize content for forward and reverse nsupdate files content_A_rec = content("server " + dns_name + "\n") content_PTR = {} for net in mappings.value('ip_ranges'): revzone = reverse_dns_zone(net) text = "server %s\n" % dns_name text += "zone %s\n" % revzone content_PTR[net] = content(text) # load the previous server list from a file if os.path.isfile('ddns_instance_state.pckl'): f = open('ddns_instance_state.pckl') prev_servers = pickle.load(f) f.close() else: prev_servers = [] # create a current list of servers and IPs that are valid for DNS updates curr_servers = {} for server in nova.servers.list(search_opts={'all_tenants': 1}): if server.status != 'ACTIVE': print "INFO: Server name %s has state %s" % (server.name, server.status) elif not valid_hostname(server.name): print "WARNING: Server name %s is not a valid hostname" % server.name elif (server.name in prev_servers) and (server.networks.values() != prev_servers[server.name]): print "WARNING: Server %s/%s is a duplicate of Server %s/%s" % (server.name, server.networks.values()[0], server.name, prev_servers[server.name][0]) elif server.name in curr_servers.keys(): # keys refers to the server names print "WARNING: Server %s/%s is a duplicate of Server %s/%s" % (server.name, server.networks.values(), server.name, curr_servers[server.name][0]) else: curr_servers[server.name] = server.networks.values() # delete servers in the previous list but not in the current list for server_name in prev_servers: if not server_name in curr_servers: # get saved ip_address ip_addresses = prev_servers[server_name] # create long hostname server_name += '.' + domain_name # update forward zone content content_A_rec.append( "update delete " + server_name + " A\n") # update reverse zone content for ip in ip_addresses[0]: rev_net, rev_dns = get_reverse_net_dns(ip, mappings.value('ip_ranges')) content_PTR[rev_net].append( "update delete " + rev_dns + " 600 IN PTR " + server_name + ".\n") # Add new servers, e.g. those in the current list but not the previous one for server_name in curr_servers: if not server_name in prev_servers: # get the ip addresses, assume there is only one network, e.g. "nebula" ip_addresses = curr_servers[server_name] # create long hostname server_name += "." + domain_name # update forward zone content with address of the last ip address forward_ip = ip_addresses[0][-1] content_A_rec.append( "update add " + server_name + " 600 A " + forward_ip + "\n") # update reverse zone content for ip in ip_addresses[0]: rev_net, rev_dns = get_reverse_net_dns(ip, mappings.value('ip_ranges')) content_PTR[rev_net].append( "update add " + rev_dns + " 600 IN PTR " + server_name + ".\n") # write content content_A_rec.write('A_records') for net in mappings.value('ip_ranges'): filename = "PTR_%s" % file_suffix(net) content_PTR[net].write(filename) # dump current server list to a file f = open('ddns_instance_state.pckl', 'w') pickle.dump(curr_servers, f) f.close()
def main(): # Authenticate Credentials try: creds = get_nova_creds() except: print 'Please set OpenStack credentials, e.g. type source openrc.sh, and try again' sys.exit() # Retrieve the Nova client nova = novaclient.Client(**creds) # get template/dictionary variables mappings = parms('ddns_config.yaml') domain_name = mappings.value('domain_name') dns_name = mappings.value('dns_shortname') + "." + domain_name # initialize content for forward and reverse nsupdate files content_A_rec = content("server " + dns_name + "\n") content_PTR = {} for net in mappings.value('ip_ranges'): revzone = reverse_dns_zone(net) text = "server %s\n" % dns_name text += "zone %s\n" % revzone content_PTR[net] = content(text) # load the previous server list from a file if os.path.isfile('ddns_instance_state.pckl'): f = open('ddns_instance_state.pckl') prev_servers = pickle.load(f) f.close() else: prev_servers = [] # create a current list of servers and IPs that are valid for DNS updates curr_servers = {} for server in nova.servers.list(search_opts={'all_tenants': 1}): if server.status != 'ACTIVE': print "INFO: Server name %s has state %s" % (server.name, server.status) elif not valid_hostname(server.name): print "WARNING: Server name %s is not a valid hostname" % server.name elif (server.name in prev_servers) and (server.networks.values() != prev_servers[server.name]): print "WARNING: Server %s/%s is a duplicate of Server %s/%s" % ( server.name, server.networks.values()[0], server.name, prev_servers[server.name][0]) elif server.name in curr_servers.keys( ): # keys refers to the server names print "WARNING: Server %s/%s is a duplicate of Server %s/%s" % ( server.name, server.networks.values(), server.name, curr_servers[server.name][0]) else: curr_servers[server.name] = server.networks.values() # delete servers in the previous list but not in the current list for server_name in prev_servers: if not server_name in curr_servers: # get saved ip_address ip_addresses = prev_servers[server_name] # create long hostname server_name += '.' + domain_name # update forward zone content content_A_rec.append("update delete " + server_name + " A\n") # update reverse zone content for ip in ip_addresses[0]: rev_net, rev_dns = get_reverse_net_dns( ip, mappings.value('ip_ranges')) content_PTR[rev_net].append("update delete " + rev_dns + " 600 IN PTR " + server_name + ".\n") # Add new servers, e.g. those in the current list but not the previous one for server_name in curr_servers: if not server_name in prev_servers: # get the ip addresses, assume there is only one network, e.g. "nebula" ip_addresses = curr_servers[server_name] # create long hostname server_name += "." + domain_name # update forward zone content with address of the last ip address forward_ip = ip_addresses[0][-1] content_A_rec.append("update add " + server_name + " 600 A " + forward_ip + "\n") # update reverse zone content for ip in ip_addresses[0]: rev_net, rev_dns = get_reverse_net_dns( ip, mappings.value('ip_ranges')) content_PTR[rev_net].append("update add " + rev_dns + " 600 IN PTR " + server_name + ".\n") # write content content_A_rec.write('A_records') for net in mappings.value('ip_ranges'): filename = "PTR_%s" % file_suffix(net) content_PTR[net].write(filename) # dump current server list to a file f = open('ddns_instance_state.pckl', 'w') pickle.dump(curr_servers, f) f.close()