Merge commit '0.8.6-100-gdca5634' into debian-devel -- inotify backend should work

* commit '0.8.6-100-gdca5634':
  RF: reordered tests + enabled gamin now that its fix is pending in Debian
  ENH+BF: filtergamin -- to be more inline with current design of filterinotify
  ENH: 1 more sleep_4_poll to guarantee difference in time stamp
  ENH: few more delays for cases relying on time stamps
pull/808/head
Yaroslav Halchenko 2012-07-20 09:55:37 -04:00
commit 954254008b
3 changed files with 61 additions and 50 deletions

View File

@ -119,6 +119,20 @@ tests.addTest(unittest.makeSuite(banmanagertestcase.AddFailure))
# ClientReader
tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest))
# Filter
tests.addTest(unittest.makeSuite(filtertestcase.IgnoreIP))
tests.addTest(unittest.makeSuite(filtertestcase.LogFile))
tests.addTest(unittest.makeSuite(filtertestcase.LogFileMonitor))
tests.addTest(unittest.makeSuite(filtertestcase.GetFailures))
tests.addTest(unittest.makeSuite(filtertestcase.DNSUtilsTests))
# DateDetector
tests.addTest(unittest.makeSuite(datedetectortestcase.DateDetectorTest))
#
# Extensive use-tests of different available filters backends
#
from server.filterpoll import FilterPoll
filters = [FilterPoll] # always available
@ -127,8 +141,7 @@ filters = [FilterPoll] # always available
# with good old unittest
try:
from server.filtergamin import FilterGamin
# That shmug plain doesn't work and stalls things ATM
# filters.append(FilterGamin)
filters.append(FilterGamin)
except:
pass
@ -142,22 +155,6 @@ for Filter_ in filters:
tests.addTest(unittest.makeSuite(
filtertestcase.get_monitor_failures_testcase(Filter_)))
# yoh: adding them (in particular datadetectortestscase before above
# get_monitor_failures_testcase's makes them fail (probably due
# to additional thread making it busier or smth like
# that)... TODO
# Filter
tests.addTest(unittest.makeSuite(filtertestcase.IgnoreIP))
tests.addTest(unittest.makeSuite(filtertestcase.LogFile))
tests.addTest(unittest.makeSuite(filtertestcase.LogFileMonitor))
tests.addTest(unittest.makeSuite(filtertestcase.GetFailures))
tests.addTest(unittest.makeSuite(filtertestcase.DNSUtilsTests))
# DateDetector
tests.addTest(unittest.makeSuite(datedetectortestcase.DateDetectorTest))
#
# Run the tests

View File

@ -17,14 +17,10 @@
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Author: Cyril Jaquier
#
# $Revision$
# Author: Cyril Jaquier, Yaroslav Halchenko
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012 Yaroslav Halchenko"
__license__ = "GPL"
from failmanager import FailManagerEmpty
@ -50,7 +46,7 @@ class FilterGamin(FileFilter):
#
# Initialize the filter object with default values.
# @param jail the jail object
def __init__(self, jail):
FileFilter.__init__(self, jail)
self.__modified = False
@ -63,9 +59,26 @@ class FilterGamin(FileFilter):
logSys.debug("Got event: " + `event` + " for " + path)
if event in (gamin.GAMCreated, gamin.GAMChanged, gamin.GAMExists):
logSys.debug("File changed: " + path)
self.getFailures(path)
self.__modified = True
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:
ticket = self.failManager.toBan()
self.jail.putFailTicket(ticket)
except FailManagerEmpty:
self.failManager.cleanup(MyTime.time())
self.dateDetector.sortTemplate()
self.__modified = False
##
# Add a log file path
@ -80,7 +93,7 @@ class FilterGamin(FileFilter):
#
# @param path the log file to delete
def delLogPath(self, path):
def _delLogPath(self, path):
self.monitor.stop_watch(path)
##
@ -92,30 +105,22 @@ class FilterGamin(FileFilter):
def run(self):
self.setActive(True)
# Gamin needs a loop to collect and dispatch events
while self._isActive():
if not self.getIdle():
# We cannot block here because we want to be able to
# exit.
if self.monitor.event_pending():
self.monitor.handle_events()
if self.__modified:
try:
while True:
ticket = self.failManager.toBan()
self.jail.putFailTicket(ticket)
except FailManagerEmpty:
self.failManager.cleanup(MyTime.time())
self.dateDetector.sortTemplate()
self.__modified = False
time.sleep(self.getSleepTime())
else:
time.sleep(self.getSleepTime())
# Cleanup Gamin
self.__cleanup()
time.sleep(self.getSleepTime())
logSys.debug(self.jail.getName() + ": filter terminated")
return True
def stop(self):
super(FilterGamin, self).stop()
self.__cleanup()
##
# Desallocates the resources used by Gamin.

View File

@ -47,6 +47,18 @@ def _killfile(f, name):
except:
pass
def _sleep_4_poll():
"""PollFilter relies on file timestamps - so we might need to
sleep to guarantee that they differ
"""
if sys.version_info[:2] <= (2,4):
# on old Python st_mtime is int, so we should give
# at least 1 sec so polling filter could detect
# the change
time.sleep(1.)
else:
time.sleep(0.1)
def _assert_equal_entries(utest, found, output, count=None):
"""Little helper to unify comparisons with the target entries
@ -201,12 +213,14 @@ class LogFileMonitor(unittest.TestCase):
# but not any longer
self.assertTrue(self.notModified())
self.assertTrue(self.notModified())
_sleep_4_poll() # to guarantee freshier mtime
for i in range(4): # few changes
# unless we write into it
self.file.write("line%d\n" % i)
self.file.flush()
self.assertTrue(self.isModified())
self.assertTrue(self.notModified())
_sleep_4_poll() # to guarantee freshier mtime
os.rename(self.name, self.name + '.old')
# we are not signaling as modified whenever
# it gets away
@ -214,6 +228,7 @@ class LogFileMonitor(unittest.TestCase):
f = open(self.name, 'a')
self.assertTrue(self.isModified())
self.assertTrue(self.notModified())
_sleep_4_poll()
f.write("line%d\n" % i)
f.flush()
self.assertTrue(self.isModified())
@ -356,13 +371,7 @@ def get_monitor_failures_testcase(Filter_):
# actions might be happening too fast in the tests,
# sleep a bit to guarantee reliable time stamps
if isinstance(self.filter, FilterPoll):
if sys.version_info[:2] <= (2,4):
# on old Python st_mtime is int, so we should give
# at least 1 sec so polling filter could detect
# the change
time.sleep(0.5)
else:
time.sleep(0.1)
_sleep_4_poll()
def isEmpty(self, delay=0.4):
# shorter wait time for not modified status