surok/surok/discovery.py
2016-11-11 21:13:40 +03:00

97 lines
2.7 KiB
Python

import dns.resolver
import dns.query
from dns.exception import DNSException
from .logger import info, warning, error, debug
import sys
# Resolve service from mesos-dns SRV record
# return dict {"servicename": [{"name": "service.f.q.d.n.", "port": 9999}]}
def resolve(app, conf):
hosts = {}
services = app['services']
domain = conf['domain']
for service in services:
hosts[service['name']] = {}
group = get_group(service, app)
if group is False:
error('Group is not defined in config, SUROK_DISCOVERY_GROUP and MARATHON_APP_ID')
error('Not in Mesos launch?')
sys.exit(2)
# Port name from app config
ports = None
try:
ports = service['ports']
except:
pass
# This is fast fix for port naming
# Will be rewrite later
fqdn = ''
if ports is not None:
for port_name in ports:
fqdn = '_' + port_name + '.' + '_' + service['name'] + '.' + group + '._tcp.' + domain
hosts[service['name']][port_name] = do_query(fqdn, conf['loglevel'])
else:
fqdn = '_' + service['name'] + '.' + group + '._tcp.' + domain
hosts[service['name']] = do_query(fqdn, conf['loglevel'])
return hosts
# Do SRV queries
# Return array: [{"name": "f.q.d.n", "port": 8876}]
def do_query(fqdn, loglevel):
servers = []
try:
resolver = dns.resolver.Resolver()
resolver.lifetime = 1
resolver.timeout = 1
query = resolver.query(fqdn, 'SRV')
for rdata in query:
info = str(rdata).split()
server = {'name': info[3][:-1], 'port': info[2]}
servers.append(server)
except DNSException as e:
if loglevel != 'info':
error("Could not resolve " + fqdn + ': ' + str(e))
return servers
# Groups switch
# Priority: config, environment, marathon environment
def get_group(service, app):
# Check group in app conf
if 'group' in service:
return service['group']
# Check environment variable
elif app['env'].get('SUROK_DISCOVERY_GROUP'):
return app['env']['SUROK_DISCOVERY_GROUP']
# Check marathon environment variable
elif app['env'].get('MARATHON_APP_ID'):
group = parse_marathon_app_id(app['env']['MARATHON_APP_ID'])
return group
else:
return False
# Parse MARATHON_APP_ID
# Return marathon.group
def parse_marathon_app_id(marathon_app_id):
marathon_app_id = marathon_app_id.split('/')
group = ''
counter = len(marathon_app_id) - 2
i = 0
while counter > i:
group = group + marathon_app_id[counter]
if counter != i + 1:
group += '.'
counter -= 1
return group