27
33
print "No Password or Passfile in client config file"
28
34
# raise RuntimeError XXX
29
35
self.password = "gazonk"
36
self.fqdn = fqdn # string
31
37
self.created = datetime.datetime.now()
38
self.last_seen = None # datetime.datetime()
33
39
if timeout is None:
34
40
timeout = options.timeout
35
self.timeout = timeout
41
self.timeout = timeout # datetime.timedelta()
37
43
interval = options.interval
38
self.interval = interval
39
self.next_check = datetime.datetime.now()
45
interval = string_to_delta(interval)
46
self.interval = interval # datetime.timedelta()
47
self.next_check = datetime.datetime.now() # datetime.datetime()
48
# Note: next_check may be in the past if checker is not None
49
self.checker = None # or a subprocess.Popen()
50
def check_action(self):
51
"""The checker said something and might have completed.
52
Check if is has, and take appropriate actions."""
53
if self.checker.poll() is None:
54
# False alarm, no result yet
56
#print "Checker for %(name)s said nothing?" % vars(self)
58
now = datetime.datetime.now()
59
if self.checker.returncode == 0:
60
print "Checker for %(name)s succeeded" % vars(self)
63
print "Checker for %(name)s failed" % vars(self)
64
while self.next_check <= now:
65
self.next_check += self.interval
67
handle_request = check_action
68
def start_checker(self):
71
self.checker = subprocess.Popen("sleep 10; fping -q -- %s"
72
% re.escape(self.fqdn),
73
stdout=subprocess.PIPE,
76
except subprocess.OSError, e:
77
print "Failed to start subprocess:", e
78
def stop_checker(self):
79
if self.checker is None:
81
os.kill(self.checker.pid, signal.SIGTERM)
82
if self.checker.poll() is None:
83
os.kill(self.checker.pid, signal.SIGKILL)
85
__del__ = stop_checker
87
if self.checker is None:
89
return self.checker.stdout.fileno()
91
"""The time when something must be done about this client
92
May be in the past."""
93
if self.last_seen is None:
94
# This client has never been seen
95
next_timeout = self.created + self.timeout
97
next_timeout = self.last_seen + self.timeout
98
if self.checker is None:
99
return min(next_timeout, self.next_check)
102
def still_valid(self, now=None):
103
"""Has this client's timeout not passed?"""
105
now = datetime.datetime.now()
106
if self.last_seen is None:
107
return now < (self.created + self.timeout)
109
return now < (self.last_seen + self.timeout)
110
def it_is_time_to_check(self, now=None):
112
now = datetime.datetime.now()
113
return self.next_check <= now
42
116
class server_metaclass(type):
216
287
client_config_object = ConfigParser.SafeConfigParser(defaults)
217
288
client_config_object.read("mandos-clients.conf")
218
clients = [Client(name=section, options=options,
219
**(dict(client_config_object.items(section))))
220
for section in client_config_object.sections()]
289
clients = Set(Client(name=section, options=options,
290
**(dict(client_config_object\
292
for section in client_config_object.sections())
222
295
udp_server = IPv6_UDPServer((in6addr_any, options.port),
230
303
credentials=cred)
233
in_, out, err = select.select((udp_server,
236
server.handle_request()
309
next_stop = min(client.next_stop() for client in clients)
310
now = datetime.datetime.now()
312
delay = next_stop - now
313
delay_seconds = (delay.days * 24 * 60 * 60
315
+ delay.microseconds / 1000000)
316
clients_with_checkers = tuple(client for client in
320
input_checks = (udp_server, tcp_server) \
321
+ clients_with_checkers
322
print "Waiting for network",
323
if clients_with_checkers:
324
print "and checkers for:",
325
for client in clients_with_checkers:
328
input, out, err = select.select(input_checks, (), (),
333
for client in clients:
334
if client.it_is_time_to_check(now=now) and \
335
client.checker is None:
336
print "Starting checker for client %(name)s" \
338
client.start_checker()
339
# delete timed-out clients
340
for client in clients.copy():
341
if not client.still_valid(now=now):
343
print "Removing client %(name)s" % vars(client)
344
clients.remove(client)
345
except KeyboardInterrupt:
349
for client in clients:
350
client.stop_checker()
239
353
if __name__ == "__main__":