[Twisted-Python] mktap dns is broken if you switch subnets
Tommi Virtanen
tv at twistedmatrix.com
Wed Apr 30 10:01:59 MDT 2003
Hi. Lately, I've been playing with using "mktap dns" as a
resolver for my laptop. Except, it's making me angry.
It doesn't reload resolv.conf. My resolv.conf nameserver list
is changed by DHCP about twice per day, atleast.
In fact, it even loads the resolv.conf only in __init__, so
the list gets stored in the tap file. I need to mktap, tap2deb
and dpkg -i whenever I switch subnets!
Here's a quick-and-stupid patch that makes it reload
resolv.conf regularly, currently made to reread it every
minute. This is "close enough". Actually, I want to make
it get a notification from somewhere..
I definitely want this implemented. Please tell what direction
should I go with the patch, and what do you think is missing
from "production quality"?
Index: twisted/names/client.py
===================================================================
RCS file: /cvs/Twisted/twisted/names/client.py,v
retrieving revision 1.31
diff -u -r1.31 client.py
--- twisted/names/client.py 29 Mar 2003 18:10:14 -0000 1.31
+++ twisted/names/client.py 30 Apr 2003 15:56:00 -0000
@@ -30,6 +30,8 @@
import socket
import os
+import errno
+import time
# Twisted imports
from twisted.python.runtime import platform
@@ -52,6 +54,10 @@
protocol = None
connections = None
+ resolv = None
+ resolv_last_read = 0
+ resolv_read_interval = 60
+
def __init__(self, resolv = None, servers = None, timeout = (1, 3, 11, 45)):
"""
@type servers: C{list} of C{(str, int)} or C{None}
@@ -78,10 +84,9 @@
else:
self.servers = servers
- if resolv and os.path.exists(resolv):
- self.parseConfig(resolv)
+ self.resolv = resolv
- if not len(self.servers):
+ if not len(self.servers) and not resolv:
raise ValueError, "No nameservers specified"
self.factory = DNSClientFactory(self, timeout)
@@ -99,20 +104,36 @@
d['connections'] = []
return d
+ def maybeParseConfig(self):
+ if self.resolv_last_read + self.resolv_read_interval < time.time():
+ self.parseConfig()
- def parseConfig(self, conf):
- lines = open(conf).readlines()
+ def parseConfig(self):
+ try:
+ file = open(self.resolv)
+ except IOError, e:
+ if e.errno == errno.ENOENT:
+ return
+ else:
+ raise
+
+ lines = file.readlines()
+ self.resolv_last_read = os.fstat(file.fileno()).st_mtime
+ file.close()
+ servers = []
for l in lines:
l = l.strip()
if l.startswith('nameserver'):
- self.servers.append((l.split()[1], dns.PORT))
- log.msg("Resolver added %r to server list" % (self.servers[-1],))
+ resolver = (l.split()[1], dns.PORT)
+ servers.append(resolver)
+ log.msg("Resolver added %r to server list" % (resolver,))
elif l.startswith('domain'):
self.domain = l.split()[1]
self.search = None
elif l.startswith('search'):
self.search = l.split()[1:]
self.domain = None
+ self.dynamicServers = servers
def pickServer(self):
@@ -122,8 +143,15 @@
TODO: Weight servers for response time so faster ones can be
preferred.
"""
- self.index = (self.index + 1) % len(self.servers)
- return self.servers[self.index]
+ self.parseConfig()
+ if not self.servers and not self.dynamicServers:
+ return None
+ self.index = ((self.index + 1)
+ % (len(self.servers) + len(self.dynamicServers)))
+ if self.index < len(self.servers):
+ return self.servers[self.index]
+ else:
+ return self.dynamicServers[self.index - len(self.servers)]
def connectionMade(self, protocol):
@@ -155,7 +183,10 @@
if timeout is None:
timeout = self.timeout
address = self.pickServer()
- d = self.protocol.query(address, queries, timeout[0])
+ if address is not None:
+ d = self.protocol.query(address, queries, timeout[0])
+ else:
+ d = defer.fail()
d.addErrback(self._reissue, address, queries, timeout[1:])
return d
@@ -186,7 +217,10 @@
@rtype: C{Deferred}
"""
if not len(self.connections):
- host, port = self.pickServer()
+ address = self.pickServer()
+ if address is None:
+ return defer.fail()
+ host, port = address
from twisted.internet import reactor
reactor.connectTCP(host, port, self.factory)
self.pending.append((defer.Deferred(), queries, timeout))
--
:(){ :|:&};:
More information about the Twisted-Python
mailing list