source: trunk/packages/sipb-xen-dns/code/dnsserver.py @ 871

Last change on this file since 871 was 851, checked in by y_z, 16 years ago
  • sipb_xen_database -> invirt.database
  • use invirt.config in dnsserver.py
  • Property svn:executable set to *
File size: 4.7 KB
RevLine 
[181]1#!/usr/bin/python
2from twisted.internet import reactor
3from twisted.names import server
4from twisted.names import dns
5from twisted.names import common
6from twisted.internet import defer
7from twisted.python import failure
8
[851]9from invirt.config import structs as config
10import invirt.database
[302]11import psycopg2
12import sqlalchemy
13import time
[181]14
15class DatabaseAuthority(common.ResolverBase):
16    """An Authority that is loaded from a file."""
17
18    soa = None
19
[851]20    def __init__(self, domains=None, database=None):
[181]21        common.ResolverBase.__init__(self)
22        if database is not None:
[851]23            invirt.database.connect(database)
24        else:
25            invirt.database.connect()
26        if domains is not None:
27            self.domains = domains
28        else:
29            self.domains = config.dns.domains
30        ns = config.dns.nameservers[0]
31        self.soa = dns.Record_SOA(mname=ns.hostname,
32                                  rname=config.dns.contact.replace('@','.',1),
[181]33                                  serial=1, refresh=3600, retry=900,
34                                  expire=3600000, minimum=21600, ttl=3600)
[851]35        self.ns = dns.Record_NS(name=ns.hostname, ttl=3600)
36        record = dns.Record_A(address=ns.ip, ttl=3600)
37        self.ns1 = dns.RRHeader(ns.hostname, dns.A, dns.IN,
[645]38                                3600, record, auth=True)
39
[582]40   
[181]41    def _lookup(self, name, cls, type, timeout = None):
[302]42        for i in range(3):
43            try:
44                value = self._lookup_unsafe(name, cls, type, timeout = None)
45            except (psycopg2.OperationalError, sqlalchemy.exceptions.SQLError):
46                if i == 2:
47                    raise
48                print "Reloading database"
49                time.sleep(0.5)
50                continue
51            else:
52                return value
53
54    def _lookup_unsafe(self, name, cls, type, timeout):
[851]55        invirt.database.clear_cache()
[582]56       
57        ttl = 900
[646]58        name = name.lower()
59        if name in self.domains:
60            domain = name
[505]61        else:
[582]62            # This works because domain will remain bound after breaking out of the loop
[505]63            for domain in self.domains:
[646]64                if name.endswith('.'+domain):
[505]65                    break
[508]66            else: #Not us
[505]67                return defer.fail(failure.Failure(dns.DomainError(name)))
[181]68        results = []
69        authority = []
[645]70        additional = [self.ns1]
[541]71        authority.append(dns.RRHeader(domain, dns.NS, dns.IN,
[582]72                                      3600, self.ns, auth=True))
73        if cls == dns.IN:
[651]74            host = name[:-len(domain)-1]
75            if not host:
76                if type in (dns.A, dns.ALL_RECORDS):
[851]77                    record = dns.Record_A(config.dns.nameservers[0].ip, ttl)
[643]78                    results.append(dns.RRHeader(name, dns.A, dns.IN, 
[582]79                                                ttl, record, auth=True))
[651]80                elif type == dns.NS:
81                    results.append(dns.RRHeader(domain, dns.NS, dns.IN,
82                                                ttl, self.ns, auth=True))
83                    authority = []
84                elif type == dns.SOA:
85                    results.append(dns.RRHeader(domain, dns.SOA, dns.IN,
86                                                ttl, self.soa, auth=True))
87            else:
88                if host:
[851]89                    value = invirt.database.Machine.get_by(name=host)
[582]90                    if value is None or not value.nics:
91                        return defer.fail(failure.Failure(dns.AuthoritativeDomainError(name)))
92                    ip = value.nics[0].ip
93                    if ip is None:  #Deactivated?
94                        return defer.fail(failure.Failure(dns.AuthoritativeDomainError(name)))
[651]95                if type in (dns.A, dns.ALL_RECORDS):
[582]96                    record = dns.Record_A(ip, ttl)
97                    results.append(dns.RRHeader(name, dns.A, dns.IN, 
98                                                ttl, record, auth=True))
[651]99                elif type == dns.SOA:
100                    results.append(dns.RRHeader(domain, dns.SOA, dns.IN,
101                                                ttl, self.soa, auth=True))
[650]102            if len(results) == 0:
103                authority = []
104                additional = []
[582]105            return defer.succeed((results, authority, additional))
106        else:
107            #Doesn't exist
108            return defer.fail(failure.Failure(dns.AuthoritativeDomainError(name)))
[181]109
110if '__main__' == __name__:
[851]111    resolver = DatabaseAuthority()
[181]112
113    verbosity = 0
114    f = server.DNSServerFactory(authorities=[resolver], verbose=verbosity)
115    p = dns.DNSDatagramProtocol(f)
116    f.noisy = p.noisy = verbosity
117   
118    reactor.listenUDP(53, p)
119    reactor.listenTCP(53, f)
120    reactor.run()
Note: See TracBrowser for help on using the repository browser.