dyndomain script
This commit is contained in:
parent
df4c58989a
commit
bc82c65c82
216
dyndomain
Executable file
216
dyndomain
Executable file
@ -0,0 +1,216 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
import configparser
|
||||
import subprocess
|
||||
import smtplib
|
||||
import time
|
||||
from email.message import EmailMessage
|
||||
from pprint import pprint
|
||||
|
||||
rundir=os.path.realpath(os.path.dirname(sys.argv[0]))
|
||||
os.chdir(rundir)
|
||||
|
||||
from sysbus import sysbus
|
||||
from ovh import ovh
|
||||
|
||||
|
||||
def load_conf():
|
||||
global zone_filename, log_filename
|
||||
global wan_hostname, zone_domain, zone_subdomain
|
||||
global hosts_list, hosts_ipv4_nat_list
|
||||
global mail_from, mail_to
|
||||
|
||||
conf = configparser.ConfigParser(allow_no_value=True)
|
||||
conf.read('home.conf')
|
||||
|
||||
zone_filename = conf['Files']['zonefile']
|
||||
log_filename = conf['Files']['logfile']
|
||||
|
||||
wan_hostname = conf['Wan']['hostname']
|
||||
zone_domain = conf['Zone']['domain']
|
||||
zone_subdomain = conf['Zone']['subdomain']
|
||||
mail_from = conf['Mail']['from']
|
||||
mail_to = conf['Mail']['to']
|
||||
|
||||
hosts_list = [ host for host in conf['Hosts'] ]
|
||||
hosts_ipv4_nat_list = [ host for host in conf['NatHosts'] ]
|
||||
|
||||
|
||||
def ping(hostname):
|
||||
cmd = "ping -c1 -w3 %s" % hostname
|
||||
ret = subprocess.run(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
return 0 if ret.returncode else 1
|
||||
|
||||
def get_ipv6_hosts():
|
||||
r = sysbus.requete('Hosts:getDevices')
|
||||
|
||||
ipv6_hosts = dict()
|
||||
for host in r['status']:
|
||||
hostname=host['hostName']
|
||||
for addr in host['addresses']:
|
||||
ipv6_hosts[hostname] = []
|
||||
if addr['family'] == 'IPv6' and addr['scope'] == 'global':
|
||||
ipv6_hosts[hostname].append(addr['ipAddress'])
|
||||
return ipv6_hosts
|
||||
|
||||
|
||||
def get_wan_addr():
|
||||
r = sysbus.requete('NMC:getWANStatus')
|
||||
wan = dict()
|
||||
wan['ipv4'] = r['data']['IPAddress']
|
||||
wan['ipv6'] = r['data']['IPv6Address']
|
||||
return wan
|
||||
|
||||
|
||||
def full_name(host, domain):
|
||||
host = host.replace('_', '-')
|
||||
return '.'.join([host, domain])
|
||||
|
||||
|
||||
def make_zone_list(wan_hostname, wan_addr, hosts, hosts_nat, domain):
|
||||
zone = []
|
||||
|
||||
wan_hostname = full_name(wan_hostname, domain)
|
||||
|
||||
if wan_addr['ipv4'] != '':
|
||||
zone.append([wan_hostname, 'A', wan_addr['ipv4']])
|
||||
for host in hosts_nat:
|
||||
zone.append([full_name(host, domain), 'A', wan_addr['ipv4']])
|
||||
|
||||
if wan_addr['ipv6'] != '':
|
||||
zone.append([wan_hostname, 'AAAA', wan_addr['ipv6']])
|
||||
for host in hosts:
|
||||
for addr in hosts[host]:
|
||||
if host in hosts_list:
|
||||
zone.append([full_name(host, domain), 'AAAA', addr])
|
||||
|
||||
return zone
|
||||
|
||||
|
||||
def read_zone_list_from_file(zone_filename):
|
||||
zone_list = []
|
||||
config = configparser.ConfigParser()
|
||||
config.read(zone_filename)
|
||||
for host in config:
|
||||
for p in config[host]:
|
||||
zone_list.append([host, p.upper(), config[host][p]])
|
||||
return zone_list
|
||||
|
||||
|
||||
def make_update_zone_list(zone_list, prev_zone_list):
|
||||
update_zone_list = []
|
||||
for entry in zone_list:
|
||||
if not any(entry == x for x in prev_zone_list):
|
||||
update_zone_list.append(entry)
|
||||
return update_zone_list
|
||||
|
||||
|
||||
def write_zone_list_to_file(zone_filename, zone_list):
|
||||
config = configparser.ConfigParser()
|
||||
for host,typefield,target in zone_list:
|
||||
if not host in config:
|
||||
config[host] = {}
|
||||
config[host][typefield] = target
|
||||
with open(zone_filename, 'w') as configfile:
|
||||
config.write(configfile)
|
||||
|
||||
|
||||
def log(msg):
|
||||
stamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
with open(log_filename, 'a') as logfile:
|
||||
for line in msg.split('\n'):
|
||||
logfile.write("%s - %s\n" % (stamp, msg))
|
||||
|
||||
|
||||
def log_update_zone(zone_list):
|
||||
for host,typea,addr in zone_list:
|
||||
log("%-20s %-6s %s" % (host, typea, addr))
|
||||
|
||||
|
||||
def ovh_update_zone(domain, zone_list):
|
||||
if not len(zone_list):
|
||||
return False
|
||||
|
||||
client = ovh.Client()
|
||||
|
||||
for host, fieldtype, target in zone_list:
|
||||
result = client.get('/domain/zone/%s/record' % domain,
|
||||
fieldType=fieldtype,
|
||||
subDomain=host)
|
||||
if len(result) == 0:
|
||||
#print("Create new entry for %s %s %s" % (host, fieldtype, target))
|
||||
client.post('/domain/zone/%s/record' % domain,
|
||||
fieldType=fieldtype,
|
||||
subDomain=host,
|
||||
target=target,
|
||||
ttl=60)
|
||||
else:
|
||||
id = result[0]
|
||||
#print("Update entry for %s %s %s" % (host, fieldtype, target))
|
||||
client.put('/domain/zone/%s/record/%ld' % (domain, id),
|
||||
target=target)
|
||||
|
||||
#print("Refresh zone %s" % domain)
|
||||
client.post('/domain/zone/%s/refresh' % domain)
|
||||
return True
|
||||
|
||||
|
||||
def send_update_mail(mail_to, mail_from, zone_domain, update_zone_list, wan):
|
||||
#print('Send email to %s' % mail_to)
|
||||
msg = EmailMessage()
|
||||
|
||||
msg['Subject'] = "Livebox update in %s" % zone_domain
|
||||
msg['From'] = mail_from
|
||||
msg['To' ] = mail_to
|
||||
|
||||
txt = "Livebox update\n\n"
|
||||
txt = txt + "WAN IPv4 : %s\n" % wan['ipv4']
|
||||
txt = txt + "WAN IPv6 : %s\n" % wan['ipv6']
|
||||
|
||||
txt = txt + "\nZone %s has been updated:\n" % zone_domain
|
||||
|
||||
for host,tp,addr in update_zone_list:
|
||||
txt = txt + " %-20s %-4s %s\n" % (host,tp,addr)
|
||||
txt = txt + '\n'
|
||||
|
||||
msg.set_content(txt)
|
||||
|
||||
s = smtplib.SMTP('localhost')
|
||||
s.send_message(msg)
|
||||
s.quit()
|
||||
|
||||
|
||||
load_conf()
|
||||
|
||||
if not ping(wan_hostname):
|
||||
log("%s is down" % wan_hostname)
|
||||
sys.exit(0)
|
||||
|
||||
sysbus.load_conf()
|
||||
sysbus.auth()
|
||||
|
||||
hosts = get_ipv6_hosts()
|
||||
wan = get_wan_addr()
|
||||
|
||||
zone_list = make_zone_list(wan_hostname, wan, hosts, hosts_ipv4_nat_list, zone_subdomain)
|
||||
prev_zone_list = read_zone_list_from_file(zone_filename)
|
||||
update_zone_list = make_update_zone_list(zone_list, prev_zone_list)
|
||||
|
||||
#print('zone_list:')
|
||||
#pprint(zone_list)
|
||||
#print('prev_zone_list:')
|
||||
#pprint(prev_zone_list)
|
||||
#print('update_zone_list:')
|
||||
#pprint(update_zone_list)
|
||||
|
||||
log_update_zone(update_zone_list)
|
||||
|
||||
sucess = ovh_update_zone(zone_domain, update_zone_list)
|
||||
|
||||
if sucess:
|
||||
new_zone_list = write_zone_list_to_file(zone_filename, prev_zone_list+update_zone_list)
|
||||
send_update_mail(mail_to, mail_from, zone_domain, update_zone_list, wan)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user