no_livebox version
* does not rely on sysbus * relies on: - a 'myip' style service to retrieve WAN IPv4 - livebox dns for IPv6
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,6 @@
 | 
				
			|||||||
 | 
					cron.log
 | 
				
			||||||
home.conf
 | 
					home.conf
 | 
				
			||||||
ovh.conf
 | 
					ovh.conf
 | 
				
			||||||
 | 
					ovh.conf.old
 | 
				
			||||||
zone.list
 | 
					zone.list
 | 
				
			||||||
zone.log
 | 
					zone.log
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +0,0 @@
 | 
				
			|||||||
[submodule "sysbus"]
 | 
					 | 
				
			||||||
	path = sysbus
 | 
					 | 
				
			||||||
	url = https://github.com/rene-d/sysbus.git
 | 
					 | 
				
			||||||
[submodule "ovh"]
 | 
					 | 
				
			||||||
	path = ovh
 | 
					 | 
				
			||||||
	url = https://github.com/ovh/python-ovh.git
 | 
					 | 
				
			||||||
							
								
								
									
										231
									
								
								dyndomain
									
									
									
									
									
								
							
							
						
						
									
										231
									
								
								dyndomain
									
									
									
									
									
								
							@@ -3,24 +3,23 @@
 | 
				
			|||||||
import sys
 | 
					import sys
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import configparser
 | 
					import configparser
 | 
				
			||||||
 | 
					import urllib.request
 | 
				
			||||||
 | 
					import urllib.parse
 | 
				
			||||||
 | 
					import socket
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
import smtplib
 | 
					 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
from email.message import EmailMessage
 | 
					 | 
				
			||||||
from pprint import pprint
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
rundir=os.path.realpath(os.path.dirname(sys.argv[0]))
 | 
					rundir=os.path.realpath(os.path.dirname(sys.argv[0]))
 | 
				
			||||||
os.chdir(rundir)
 | 
					os.chdir(rundir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from sysbus import sysbus
 | 
					 | 
				
			||||||
from ovh import ovh
 | 
					from ovh import ovh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def load_conf():
 | 
					def load_conf():
 | 
				
			||||||
    global zone_filename, log_filename
 | 
					    global zone_filename, log_filename
 | 
				
			||||||
    global wan_hostname, zone_domain, zone_subdomain
 | 
					    global wan_hostname
 | 
				
			||||||
    global hosts_list, hosts_ipv4_nat_list
 | 
					    global hosts6_list, hosts4_list
 | 
				
			||||||
    global mail_from, mail_to
 | 
					    global zone_domain, zone_subdomain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    conf = configparser.ConfigParser(allow_no_value=True)
 | 
					    conf = configparser.ConfigParser(allow_no_value=True)
 | 
				
			||||||
    conf.read('home.conf')
 | 
					    conf.read('home.conf')
 | 
				
			||||||
@@ -29,188 +28,118 @@ def load_conf():
 | 
				
			|||||||
    log_filename = conf['Files']['logfile']
 | 
					    log_filename = conf['Files']['logfile']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wan_hostname = conf['Wan']['hostname']
 | 
					    wan_hostname = conf['Wan']['hostname']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hosts6_list = [ host for host in conf['Hosts'] ]
 | 
				
			||||||
 | 
					    hosts4_list = [ host for host in conf['NatHosts'] ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    zone_domain = conf['Zone']['domain']
 | 
					    zone_domain = conf['Zone']['domain']
 | 
				
			||||||
    zone_subdomain = conf['Zone']['subdomain']
 | 
					    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):
 | 
					def get_host_ipv6(name):
 | 
				
			||||||
    cmd = "ping -c1 -w3 %s" % hostname
 | 
					    try:
 | 
				
			||||||
    ret = subprocess.run(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 | 
					        res = socket.getaddrinfo(name, None, socket.AF_INET6, socket.SOCK_STREAM)
 | 
				
			||||||
    return 0 if ret.returncode else 1
 | 
					    except socket.gaierror:
 | 
				
			||||||
 | 
					        return []
 | 
				
			||||||
def get_ipv6_hosts():
 | 
					    ips = [ r[4][0] for r in res ]
 | 
				
			||||||
    r = sysbus.requete('Hosts:getDevices')
 | 
					    return ips
 | 
				
			||||||
 | 
					 | 
				
			||||||
    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():
 | 
					def get_wan_ipv4():
 | 
				
			||||||
    r = sysbus.requete('NMC:getWANStatus')
 | 
					    try:
 | 
				
			||||||
    wan = dict()
 | 
					        f = urllib.request.urlopen('https://ipv4.wtfismyip.com/text')
 | 
				
			||||||
    wan['ipv4'] = r['data']['IPAddress']
 | 
					        return f.read().decode('utf-8').split('\n')[0]
 | 
				
			||||||
    wan['ipv6'] = r['data']['IPv6Address']
 | 
					    except urllib.error.URLError as e:
 | 
				
			||||||
    return wan
 | 
					        print(e)
 | 
				
			||||||
 | 
					        sys.exit(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def full_name(host, domain):
 | 
					def get_wan_ipv6():
 | 
				
			||||||
    host = host.replace('_', '-')
 | 
					    return get_host_ipv6(wan_hostname)[0]
 | 
				
			||||||
    return '.'.join([host, domain])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def make_zone_list(wan_hostname, wan_addr, hosts, hosts_nat, domain):
 | 
					def ping_alive(ip):
 | 
				
			||||||
 | 
					    cmd = ['fping6', '-q', '-B1', ip]
 | 
				
			||||||
 | 
					    ret = subprocess.call(cmd)
 | 
				
			||||||
 | 
					    if not ret:
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def make_zone_list(wan_ipv4, hosts4, hosts6, subdomain):
 | 
				
			||||||
    zone = []
 | 
					    zone = []
 | 
				
			||||||
   
 | 
					    for host in hosts4:
 | 
				
			||||||
    wan_hostname = full_name(wan_hostname, domain)
 | 
					        entry = [ host+'.'+subdomain, 'A', wan_ipv4 ]
 | 
				
			||||||
 | 
					        zone.append(entry)
 | 
				
			||||||
    if wan_addr['ipv4'] != '':
 | 
					    for host in hosts6:
 | 
				
			||||||
        zone.append([wan_hostname, 'A', wan_addr['ipv4']])
 | 
					        for ip in get_host_ipv6(host):
 | 
				
			||||||
        for host in hosts_nat:
 | 
					            if ping_alive(ip):
 | 
				
			||||||
            zone.append([full_name(host, domain), 'A', wan_addr['ipv4']])
 | 
					                entry = [ host+'.'+subdomain, 'AAAA', ip ]
 | 
				
			||||||
 | 
					                zone.append(entry)
 | 
				
			||||||
    if wan_addr['ipv6'] != '':
 | 
					    zone.sort()
 | 
				
			||||||
        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
 | 
					    return zone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def read_zone_list_from_file(zone_filename):
 | 
					def read_zone_list_from_file(zone_filename):
 | 
				
			||||||
    zone_list = []
 | 
					    zone = []
 | 
				
			||||||
    config = configparser.ConfigParser()
 | 
					    try:
 | 
				
			||||||
    config.read(zone_filename)
 | 
					        with open(zone_filename, 'r') as zf:
 | 
				
			||||||
    for host in config:
 | 
					            for line in zf:
 | 
				
			||||||
        for p in config[host]:
 | 
					                line = line.rstrip('\n')
 | 
				
			||||||
            zone_list.append([host, p.upper(), config[host][p]])
 | 
					                entry = line.split(' ')
 | 
				
			||||||
    return zone_list
 | 
					                if entry[1] not in ['A', 'AAAA']:
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                zone.append(entry)
 | 
				
			||||||
def make_update_zone_list(zone_list, prev_zone_list):
 | 
					    except FileNotFoundError:
 | 
				
			||||||
    update_zone_list = []
 | 
					        pass
 | 
				
			||||||
    for entry in zone_list:
 | 
					    return zone
 | 
				
			||||||
        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):
 | 
					def write_zone_list_to_file(zone_filename, zone_list):
 | 
				
			||||||
    config = configparser.ConfigParser()
 | 
					    with open(zone_filename, 'w') as zf:
 | 
				
			||||||
    for host,typefield,target in zone_list:
 | 
					        for entry in zone_list:
 | 
				
			||||||
        if not host in config:
 | 
					            line = ' '.join(entry)+'\n'
 | 
				
			||||||
            config[host] = {}
 | 
					            zf.write(line)
 | 
				
			||||||
        config[host][typefield] = target
 | 
					 | 
				
			||||||
    with open(zone_filename, 'w') as configfile:
 | 
					 | 
				
			||||||
        config.write(configfile)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def ovh_update_zone(domain, prev_zone_list, zone_list):
 | 
				
			||||||
def log(msg):
 | 
					    if not len(zone_list) and not len(remove_zone_list):
 | 
				
			||||||
    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
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    client = ovh.Client()
 | 
					    client = ovh.Client()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for host, fieldtype, target in zone_list:
 | 
					    print("\ndate:", time.strftime("%c"))
 | 
				
			||||||
 | 
					    for host, fieldtype, target in prev_zone_list:
 | 
				
			||||||
        result = client.get('/domain/zone/%s/record' % domain,
 | 
					        result = client.get('/domain/zone/%s/record' % domain,
 | 
				
			||||||
                            fieldType=fieldtype,
 | 
					                            fieldType=fieldtype,
 | 
				
			||||||
                            subDomain=host)
 | 
					                            subDomain=host)
 | 
				
			||||||
        if len(result) == 0:
 | 
					        for id in result:
 | 
				
			||||||
            #print("Create new entry for %s %s %s" % (host, fieldtype, target))
 | 
					            print("Deleting old entry for %s %s" % (host, fieldtype))
 | 
				
			||||||
 | 
					            client.delete('/domain/zone/%s/record/%ld' % (domain, id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for host, fieldtype, target in zone_list:
 | 
				
			||||||
 | 
					        print("Create new entry for %s %s %s" % (host, fieldtype, target))
 | 
				
			||||||
        client.post('/domain/zone/%s/record' % domain,
 | 
					        client.post('/domain/zone/%s/record' % domain,
 | 
				
			||||||
                fieldType=fieldtype,
 | 
					                fieldType=fieldtype,
 | 
				
			||||||
                subDomain=host,
 | 
					                subDomain=host,
 | 
				
			||||||
                target=target,
 | 
					                target=target,
 | 
				
			||||||
                ttl=60)
 | 
					                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)
 | 
					    print("Refresh zone %s" % domain)
 | 
				
			||||||
    client.post('/domain/zone/%s/refresh' % domain)
 | 
					    client.post('/domain/zone/%s/refresh' % domain)
 | 
				
			||||||
    return True
 | 
					    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()
 | 
					load_conf()
 | 
				
			||||||
 | 
					hosts4_list.append(wan_hostname)
 | 
				
			||||||
 | 
					hosts6_list.append(wan_hostname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if not ping(wan_hostname):
 | 
					wan_ipv4 = get_wan_ipv4()
 | 
				
			||||||
    log("%s is down" % wan_hostname)
 | 
					wan_ipv6 = get_wan_ipv6()
 | 
				
			||||||
    sys.exit(0)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
sysbus.load_conf()
 | 
					zone_list = make_zone_list(wan_ipv4, hosts4_list, hosts6_list, zone_subdomain)
 | 
				
			||||||
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)
 | 
					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)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if zone_list != prev_zone_list:
 | 
				
			||||||
 | 
					    success = ovh_update_zone(zone_domain, prev_zone_list, zone_list)
 | 
				
			||||||
 | 
					    write_zone_list_to_file(zone_filename, zone_list)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										40
									
								
								notes.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								notes.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					get ipv4 wan
 | 
				
			||||||
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ curl -4 http://ifconfig.co
 | 
				
			||||||
 | 
					90.116.135.67
 | 
				
			||||||
 | 
					[please limits to 1 req/min]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ curl https://ipinfo.io/ip
 | 
				
			||||||
 | 
					90.116.135.67
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ curl https://ipv4.wtfismyip.com/text
 | 
				
			||||||
 | 
					90.116.135.67
 | 
				
			||||||
 | 
					[1 request per minute]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get ipv6 wan
 | 
				
			||||||
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ host livebox.home
 | 
				
			||||||
 | 
					livebox.home has address 192.168.1.1
 | 
				
			||||||
 | 
					livebox.home has IPv6 address 2a01:cb1d:164:f500:327c:b2ff:fe9e:cf16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get ipv6 host
 | 
				
			||||||
 | 
					-------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ host arwen.home
 | 
				
			||||||
 | 
					arwen.home has address 192.168.1.113
 | 
				
			||||||
 | 
					arwen.home has IPv6 address 2a01:cb1d:164:f500:8ff:3eea:a3b2:714e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ host arwen.home
 | 
				
			||||||
 | 
					arwen.home has address 192.168.1.113
 | 
				
			||||||
 | 
					arwen.home has IPv6 address 2a01:cb1d:164:f500:3df0:c245:7d7a:26e2
 | 
				
			||||||
 | 
					arwen.home has IPv6 address 2a01:cb1d:164:f500:8ff:3eea:a3b2:714e
 | 
				
			||||||
 | 
					arwen.home has IPv6 address 2a01:cb1d:164:f500:28af:1644:6308:f13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ fping6 2a01:cb1d:164:f500:8ff:3eea:a3b2:714e 2a01:cb1d:164:f500:3df0:c245:7d7a:26e2 2a01:cb1d:164:f500:28af:1644:6308:f13
 | 
				
			||||||
 | 
					2a01:cb1d:164:f500:8ff:3eea:a3b2:714e is alive
 | 
				
			||||||
 | 
					2a01:cb1d:164:f500:3df0:c245:7d7a:26e2 is unreachable
 | 
				
			||||||
 | 
					2a01:cb1d:164:f500:28af:1644:6308:f13 is unreachable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -8,7 +8,7 @@ client = ovh.Client()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ck = client.new_consumer_key_request()
 | 
					ck = client.new_consumer_key_request()
 | 
				
			||||||
ck.add_rules(ovh.API_READ_WRITE_SAFE, '/domain/zone/%s/record' % domain)
 | 
					ck.add_rules(ovh.API_READ_WRITE_SAFE, '/domain/zone/%s/record' % domain)
 | 
				
			||||||
ck.add_rules(ovh.API_READ_WRITE_SAFE, '/domain/zone/%s/record/*' % domain)
 | 
					ck.add_rules(ovh.API_READ_WRITE,      '/domain/zone/%s/record/*' % domain)
 | 
				
			||||||
ck.add_rules(ovh.API_READ_WRITE_SAFE, '/domain/zone/%s/refresh' % domain)
 | 
					ck.add_rules(ovh.API_READ_WRITE_SAFE, '/domain/zone/%s/refresh' % domain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
validation = ck.request()
 | 
					validation = ck.request()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								sysbus
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								sysbus
									
									
									
									
									
								
							 Submodule sysbus deleted from bf7689ce0a
									
								
							
		Reference in New Issue
	
	Block a user