1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import operator
24 import random
25 import socket
26
27 from twisted.internet import base, defer, threads, reactor
28 from twisted.python import threadpool
29 from flumotion.common import log
30
31 DEFAULT_PRIORITY = 1.0
32 DEFAULT_REFRESH_TIMEOUT = 300
33
34 LOG_CATEGORY = "server-selector"
35
36
38
42
44 if timeout:
45 timeoutDelay = reduce(operator.add, timeout)
46 else:
47 timeoutDelay = 60
48 userDeferred = defer.Deferred()
49
50
51 lookupDeferred = threads.deferToThread(
52 self.socket.gethostbyname_ex, name)
53 cancelCall = self.reactor.callLater(
54 timeoutDelay, self._cleanup, name, lookupDeferred)
55 self._runningQueries[lookupDeferred] = (userDeferred, cancelCall)
56 lookupDeferred.addBoth(self._checkTimeout, name, lookupDeferred)
57 return userDeferred
58
59
61
62 logCategory = LOG_CATEGORY
63
65 self.servers = {}
66 self.hostnames = {}
67 self.timeout = timeout
68 self.socket = socket
69
70 self._resolver = ThreadedResolver(reactor, sk)
71 self._refresh = None
72
74 ip_list = h[2]
75 for ip in ip_list:
76 s = Server(ip, port, priority)
77 if s not in self.servers[priority]:
78 self.servers[priority].append(s)
79
80 self.hostnames[hostname] = (ip_list, priority, port)
81
86
88 """
89 Add a hostname to the list of servers, with a priority. (in
90 increasing order, 1 comes before 2).
91
92 @return None
93 """
94 self.hostnames[hostname] = ([], priority, port)
95 if priority not in self.servers:
96 self.servers[priority] = []
97
98 d = self._resolver.getHostByNameEx(hostname)
99 d.addCallbacks(self._addCallback,
100 self._addErrback,
101 callbackArgs=(hostname, port, priority))
102 return d
103
105 """
106 Order the looked up servers by priority, and return them.
107
108 @return a generator of Server
109 """
110 priorities = self.servers.keys()
111 priorities.sort()
112 for p in priorities:
113 servers = self.servers[p]
114 random.shuffle(servers)
115 for s in servers:
116 yield s
117
119
120 new_ips = host[2]
121 old_ips, priority, port = self.hostnames[hostname]
122 to_be_added = [ip for ip in new_ips if ip not in old_ips]
123 to_be_removed = [ip for ip in old_ips if ip not in new_ips]
124 servers = self.servers[priority]
125 for ip in to_be_added:
126 servers.append(Server(ip, port, priority))
127 self.hostnames[hostname][0].append(ip)
128 for ip in to_be_removed:
129 for s in servers:
130 if s.ip == ip:
131 servers.remove(s)
132 self.hostnames[hostname][0].remove(ip)
133 self.servers[priority] = servers
134
146
150
153
156
158 if self._refresh:
159 self._refresh.cancel()
160 self._refresh = None
161
162
164
165 - def __init__(self, ip, port, priority):
166 self.ip = ip
167 self.port = port
168 self.priority = priority
169
172
175
177 return self.__dict__ == other.__dict__
178