mirror of https://github.com/fail2ban/fail2ban
BF+RF: pyinotify refreshes watcher upon CREATE, unified/simplified *(add|del)LogPath among *Filters
* all of the *Filters had too much of common logic in their *LogPath methods, which is now handled by FileFilter and derived classes only add custom actions in corresponding _(add|del)LogPath methods pyinotify: * upon CREATE event: - unknown files should not be handled at all - "watcher" for the monitored files should be recreated. Lead to adding _(add|del)FileWatcher helper methods * callback now obtains full event to judge what to dopull/8/merge
parent
08564bda1a
commit
d9248a6cf8
|
@ -395,8 +395,19 @@ class FileFilter(Filter):
|
|||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path, tail = False):
|
||||
container = FileContainer(path, tail)
|
||||
self.__logPath.append(container)
|
||||
if self.containsLogPath(path):
|
||||
logSys.error(path + " already exists")
|
||||
else:
|
||||
container = FileContainer(path, tail)
|
||||
self.__logPath.append(container)
|
||||
logSys.info("Added logfile = %s" % path)
|
||||
self._addLogPath(path) # backend specific
|
||||
|
||||
def _addLogPath(self, path):
|
||||
# nothing to do by default
|
||||
# to be overriden by backends
|
||||
pass
|
||||
|
||||
|
||||
##
|
||||
# Delete a log path
|
||||
|
@ -407,8 +418,15 @@ class FileFilter(Filter):
|
|||
for log in self.__logPath:
|
||||
if log.getFileName() == path:
|
||||
self.__logPath.remove(log)
|
||||
logSys.info("Removed logfile = %s" % path)
|
||||
self._delLogPath(path)
|
||||
return
|
||||
|
||||
def _delLogPath(self, path):
|
||||
# nothing to do by default
|
||||
# to be overriden by backends
|
||||
pass
|
||||
|
||||
##
|
||||
# Get the log file path
|
||||
#
|
||||
|
|
|
@ -72,27 +72,17 @@ class FilterGamin(FileFilter):
|
|||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path, tail = False):
|
||||
if self.containsLogPath(path):
|
||||
logSys.error(path + " already exists")
|
||||
else:
|
||||
self.monitor.watch_file(path, self.callback)
|
||||
FileFilter.addLogPath(self, path, tail)
|
||||
logSys.info("Added logfile = %s" % path)
|
||||
|
||||
def _addLogPath(self, path):
|
||||
self.monitor.watch_file(path, self.callback)
|
||||
|
||||
##
|
||||
# Delete a log path
|
||||
#
|
||||
# @param path the log file to delete
|
||||
|
||||
|
||||
def delLogPath(self, path):
|
||||
if not self.containsLogPath(path):
|
||||
logSys.error(path + " is not monitored")
|
||||
else:
|
||||
self.monitor.stop_watch(path)
|
||||
FileFilter.delLogPath(self, path)
|
||||
logSys.info("Removed logfile = %s" % path)
|
||||
|
||||
self.monitor.stop_watch(path)
|
||||
|
||||
##
|
||||
# Main loop.
|
||||
#
|
||||
|
|
|
@ -63,28 +63,18 @@ class FilterPoll(FileFilter):
|
|||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path, tail = False):
|
||||
if self.containsLogPath(path):
|
||||
logSys.error(path + " already exists")
|
||||
else:
|
||||
self.__lastModTime[path] = 0
|
||||
self.__file404Cnt[path] = 0
|
||||
FileFilter.addLogPath(self, path, tail)
|
||||
logSys.info("Added logfile = %s" % path)
|
||||
def _addLogPath(self, path):
|
||||
self.__lastModTime[path] = 0
|
||||
self.__file404Cnt[path] = 0
|
||||
|
||||
##
|
||||
# Delete a log path
|
||||
#
|
||||
# @param path the log file to delete
|
||||
|
||||
def delLogPath(self, path):
|
||||
if not self.containsLogPath(path):
|
||||
logSys.error(path + " is not monitored")
|
||||
else:
|
||||
del self.__lastModTime[path]
|
||||
del self.__file404Cnt[path]
|
||||
FileFilter.delLogPath(self, path)
|
||||
logSys.info("Removed logfile = %s" % path)
|
||||
def _delLogPath(self, path):
|
||||
del self.__lastModTime[path]
|
||||
del self.__file404Cnt[path]
|
||||
|
||||
##
|
||||
# Main loop.
|
||||
|
|
|
@ -57,7 +57,29 @@ class FilterPyinotify(FileFilter):
|
|||
logSys.debug("Created FilterPyinotify")
|
||||
|
||||
|
||||
def callback(self, path):
|
||||
def callback(self, event):
|
||||
path = event.pathname
|
||||
if event.mask == pyinotify.IN_CREATE:
|
||||
# check if that is a file we care about
|
||||
if not path in self.__watches:
|
||||
logSys.debug("Ignoring creation of %s we do not monitor" % path)
|
||||
return
|
||||
else:
|
||||
# we need to substitute the watcher with a new one, so first
|
||||
# remove old one
|
||||
self._delFileWatcher(path)
|
||||
# place a new one
|
||||
self._addFileWatcher(path)
|
||||
|
||||
self._process_file(path)
|
||||
|
||||
|
||||
def _process_file(self, path):
|
||||
"""Process a given file
|
||||
|
||||
TODO -- RF:
|
||||
this is a common logic and must be shared/provided by FileFilter
|
||||
"""
|
||||
self.getFailures(path)
|
||||
try:
|
||||
while True:
|
||||
|
@ -68,57 +90,58 @@ class FilterPyinotify(FileFilter):
|
|||
self.dateDetector.sortTemplate()
|
||||
self.__modified = False
|
||||
|
||||
|
||||
def _addFileWatcher(self, path):
|
||||
wd = self.__monitor.add_watch(path, pyinotify.IN_MODIFY)
|
||||
self.__watches.update(wd)
|
||||
logSys.debug("Added file watcher for %s" % path)
|
||||
# process the file since we did get even
|
||||
self._process_file(path)
|
||||
|
||||
|
||||
def _delFileWatcher(self, path):
|
||||
wdInt = self.__watches[path]
|
||||
wd = self.__monitor.rm_watch(wdInt)
|
||||
if wd[wdInt]:
|
||||
del self.__watches[path]
|
||||
logSys.debug("Removed file watcher for %s" % path)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
##
|
||||
# Add a log file path
|
||||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path, tail=False):
|
||||
if self.containsLogPath(path):
|
||||
logSys.error(path + " already exists")
|
||||
else:
|
||||
wd = self.__monitor.add_watch(path, pyinotify.IN_MODIFY)
|
||||
self.__watches.update(wd)
|
||||
def _addLogPath(self, path):
|
||||
path_dir = dirname(path)
|
||||
if not (path_dir in self.__watches):
|
||||
# we need to watch also the directory for IN_CREATE
|
||||
self.__watches.update(
|
||||
self.__monitor.add_watch(path_dir, pyinotify.IN_CREATE))
|
||||
logSys.debug("Added monitor for the parent directory %s" % path_dir)
|
||||
|
||||
FileFilter.addLogPath(self, path, tail)
|
||||
logSys.info("Added logfile = %s" % path)
|
||||
self._addFileWatcher(path)
|
||||
|
||||
path_dir = dirname(path)
|
||||
if not (path_dir in self.__watches):
|
||||
# we need to watch also the directory for IN_CREATE
|
||||
self.__watches.update(
|
||||
self.__monitor.add_watch(path_dir, pyinotify.IN_CREATE))
|
||||
logSys.debug("Monitor also parent directory %s" % path_dir)
|
||||
|
||||
# sniff the file
|
||||
self.callback(path)
|
||||
|
||||
##
|
||||
# Delete a log path
|
||||
#
|
||||
# @param path the log file to delete
|
||||
|
||||
def delLogPath(self, path):
|
||||
if not self.containsLogPath(path):
|
||||
logSys.error(path + " is not monitored")
|
||||
else:
|
||||
wdInt = self.__watches[path]
|
||||
wd = self.__monitor.rm_watch(wdInt)
|
||||
if wd[wdInt]:
|
||||
del self.__watches[path]
|
||||
FileFilter.delLogPath(self, path)
|
||||
logSys.info("Removed logfile = %s" % path)
|
||||
else:
|
||||
logSys.error("Failed to remove watch on path: %s", path)
|
||||
def _delLogPath(self, path):
|
||||
if not self._delFileWatcher(path):
|
||||
logSys.error("Failed to remove watch on path: %s", path)
|
||||
|
||||
path_dir = dirname(path)
|
||||
if not len([k for k in self.__watches
|
||||
if k.startswith(path_dir + pathsep)]):
|
||||
# Remove watches for the directory
|
||||
# since there is no other monitored file under this directory
|
||||
wdInt = self.__watches.pop(path_dir)
|
||||
_ = self.__monitor.rm_watch(wdInt)
|
||||
logSys.debug("Remove monitor for the parent directory %s" % path_dir)
|
||||
path_dir = dirname(path)
|
||||
if not len([k for k in self.__watches
|
||||
if k.startswith(path_dir + pathsep)]):
|
||||
# Remove watches for the directory
|
||||
# since there is no other monitored file under this directory
|
||||
wdInt = self.__watches.pop(path_dir)
|
||||
_ = self.__monitor.rm_watch(wdInt)
|
||||
logSys.debug("Removed monitor for the parent directory %s" % path_dir)
|
||||
|
||||
|
||||
##
|
||||
|
@ -169,4 +192,4 @@ class ProcessPyinotify(pyinotify.ProcessEvent):
|
|||
# just need default, since using mask on watch to limit events
|
||||
def process_default(self, event):
|
||||
logSys.debug("Callback for Event: %s" % event)
|
||||
self.__FileFilter.callback(event.pathname)
|
||||
self.__FileFilter.callback(event)
|
||||
|
|
Loading…
Reference in New Issue