1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
"""Bcfg2.Server.FileMonitor provides the support for monitoring files."""
import os
import sys
import fnmatch
import logging
import pkgutil
from time import sleep, time
logger = logging.getLogger(__name__)
class Event(object):
def __init__(self, request_id, filename, code):
self.requestID = request_id
self.filename = filename
self.action = code
def code2str(self):
"""return static code for event"""
return self.action
def __str__(self):
return "%s: %s %s" % (self.__class__.__name__,
self.filename, self.action)
def __repr__(self):
return "%s (request ID %s)" % (str(self), self.requestID)
class FileMonitor(object):
"""File Monitor baseclass."""
def __init__(self, ignore=None, debug=False):
object.__init__(self)
self.debug = debug
self.handles = dict()
self.events = []
if ignore is None:
ignore = []
self.ignore = ignore
def __str__(self):
return "%s: %s" % (__name__, self.__class__.__name__)
def __repr__(self):
return "%s (%s events, fd %s)" % (str(self), len(events), self.fileno)
def should_ignore(self, event):
for pattern in self.ignore:
if (fnmatch.fnmatch(event.filename, pattern) or
fnmatch.fnmatch(os.path.split(event.filename)[-1], pattern)):
if self.debug:
logger.info("Ignoring %s" % event)
return True
return False
def pending(self):
return bool(self.events)
def get_event(self):
return self.events.pop(0)
def fileno(self):
return 0
def handle_one_event(self, event):
if self.should_ignore(event):
return
if event.requestID not in self.handles:
logger.info("Got event for unexpected id %s, file %s" %
(event.requestID, event.filename))
return
if self.debug:
logger.info("Dispatching event %s %s to obj %s" %
(event.code2str(), event.filename,
self.handles[event.requestID]))
try:
self.handles[event.requestID].HandleEvent(event)
except:
err = sys.exc_info()[1]
logger.error("Error in handling of event for %s: %s" %
(event.filename, err))
def handle_event_set(self, lock=None):
count = 1
event = self.get_event()
start = time()
if lock:
lock.acquire()
try:
self.handle_one_event(event)
while self.pending():
self.handle_one_event(self.get_event())
count += 1
except:
pass
if lock:
lock.release()
end = time()
logger.info("Handled %d events in %.03fs" % (count, (end - start)))
def handle_events_in_interval(self, interval):
end = time() + interval
while time() < end:
if self.pending():
self.handle_event_set()
end = time() + interval
else:
sleep(0.5)
def shutdown(self):
pass
available = dict()
# todo: loading the monitor drivers should be automatic
from Bcfg2.Server.FileMonitor.Pseudo import Pseudo
available['pseudo'] = Pseudo
try:
from Bcfg2.Server.FileMonitor.Fam import Fam
available['fam'] = Fam
except ImportError:
pass
try:
from Bcfg2.Server.FileMonitor.Gamin import Gamin
available['gamin'] = Gamin
except ImportError:
pass
try:
from Bcfg2.Server.FileMonitor.Inotify import Inotify
available['inotify'] = Inotify
except ImportError:
pass
for fdrv in sorted(available.keys(), key=lambda k: available[k].__priority__):
if fdrv in available:
available['default'] = available[fdrv]
break
|