diff options
Diffstat (limited to 'src/lib/Bcfg2/Server/FileMonitor/Inotify.py')
-rw-r--r-- | src/lib/Bcfg2/Server/FileMonitor/Inotify.py | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/lib/Bcfg2/Server/FileMonitor/Inotify.py b/src/lib/Bcfg2/Server/FileMonitor/Inotify.py new file mode 100644 index 000000000..50c724279 --- /dev/null +++ b/src/lib/Bcfg2/Server/FileMonitor/Inotify.py @@ -0,0 +1,64 @@ +""" Inotify driver for file alteration events """ + +import os +import stat +import logging +import operator +import pyinotify +from Bcfg2.Server.FileMonitor import Event +from Bcfg2.Server.FileMonitor.Pseudo import Pseudo + +logger = logging.getLogger(__name__) + +class Inotify(Pseudo, pyinotify.ProcessEvent): + __priority__ = 1 + mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY + action_map = {pyinotify.IN_CREATE: 'created', + pyinotify.IN_DELETE: 'deleted', + pyinotify.IN_MODIFY: 'changed'} + + def __init__(self, ignore=None, debug=False): + Pseudo.__init__(self, ignore=ignore, debug=debug) + self.wm = pyinotify.WatchManager() + self.notifier = pyinotify.ThreadedNotifier(self.wm, self) + self.notifier.start() + + def fileno(self): + return self.wm.get_fd() + + def process_default(self, ievent): + action = ievent.maskname + for amask, aname in self.action_map.items(): + if ievent.mask & amask: + action = aname + break + # FAM-style file monitors return the full path to the parent + # directory that is being watched, relative paths to anything + # contained within the directory + watch = self.wm.watches[ievent.wd] + if watch.path == ievent.pathname: + path = ievent.pathname + else: + # relative path + path = os.path.basename(ievent.pathname) + evt = Event(ievent.wd, path, action) + self.events.append(evt) + + def AddMonitor(self, path, obj): + res = self.wm.add_watch(path, self.mask, quiet=False) + if not res: + # if we didn't get a return, but we also didn't get an + # exception, we're already watching this directory, so we + # need to find the watch descriptor for it + for wd, watch in self.wm.watches.items(): + if watch.path == path: + wd = watch.wd + else: + wd = res[path] + + # inotify doesn't produce initial 'exists' events, so we + # inherit from Pseudo to produce those + return Pseudo.AddMonitor(self, path, obj, handleID=wd) + + def shutdown(self): + self.notifier.stop() |