|
|
|
@ -98,7 +98,9 @@ def _test_raw_input(*args):
|
|
|
|
|
fail2banclient.raw_input = _test_raw_input
|
|
|
|
|
|
|
|
|
|
# prevents change logging params, log capturing, etc:
|
|
|
|
|
fail2bancmdline.PRODUCTION = False
|
|
|
|
|
fail2bancmdline.PRODUCTION = \
|
|
|
|
|
fail2banclient.PRODUCTION = \
|
|
|
|
|
fail2banserver.PRODUCTION = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ExitException(fail2bancmdline.ExitException):
|
|
|
|
@ -117,9 +119,9 @@ def _out_file(fn): # pragma: no cover
|
|
|
|
|
def _start_params(tmp, use_stock=False, logtarget="/dev/null"):
|
|
|
|
|
cfg = tmp+"/config"
|
|
|
|
|
if use_stock and STOCK:
|
|
|
|
|
# copy config:
|
|
|
|
|
# copy config (sub-directories as alias):
|
|
|
|
|
def ig_dirs(dir, files):
|
|
|
|
|
return [f for f in files if not os.path.isfile(os.path.join(dir, f))]
|
|
|
|
|
return [f for f in files if os.path.isdir(os.path.join(dir, f))]
|
|
|
|
|
shutil.copytree(STOCK_CONF_DIR, cfg, ignore=ig_dirs)
|
|
|
|
|
os.symlink(STOCK_CONF_DIR+"/action.d", cfg+"/action.d")
|
|
|
|
|
os.symlink(STOCK_CONF_DIR+"/filter.d", cfg+"/filter.d")
|
|
|
|
@ -169,6 +171,47 @@ def _start_params(tmp, use_stock=False, logtarget="/dev/null"):
|
|
|
|
|
"--logtarget", logtarget, "--loglevel", "DEBUG", "--syslogsocket", "auto",
|
|
|
|
|
"-s", tmp+"/f2b.sock", "-p", tmp+"/f2b.pid")
|
|
|
|
|
|
|
|
|
|
def _kill_srv(pidfile): # pragma: no cover
|
|
|
|
|
def _pid_exists(pid):
|
|
|
|
|
try:
|
|
|
|
|
os.kill(pid, 0)
|
|
|
|
|
return True
|
|
|
|
|
except OSError:
|
|
|
|
|
return False
|
|
|
|
|
logSys.debug("-- cleanup: %r", (pidfile, os.path.isdir(pidfile)))
|
|
|
|
|
if os.path.isdir(pidfile):
|
|
|
|
|
piddir = pidfile
|
|
|
|
|
pidfile = piddir + "/f2b.pid"
|
|
|
|
|
if not os.path.isfile(pidfile):
|
|
|
|
|
pidfile = piddir + "/fail2ban.pid"
|
|
|
|
|
if not os.path.isfile(pidfile):
|
|
|
|
|
logSys.debug("--- cleanup: no pidfile for %r", piddir)
|
|
|
|
|
return True
|
|
|
|
|
f = pid = None
|
|
|
|
|
try:
|
|
|
|
|
logSys.debug("--- cleanup pidfile: %r", pidfile)
|
|
|
|
|
f = open(pidfile)
|
|
|
|
|
pid = f.read().split()[1]
|
|
|
|
|
pid = int(pid)
|
|
|
|
|
logSys.debug("--- cleanup pid: %r", pid)
|
|
|
|
|
if pid <= 0:
|
|
|
|
|
raise ValueError('pid %s of %s is invalid' % (pid, pidfile))
|
|
|
|
|
if not _pid_exists(pid):
|
|
|
|
|
return True
|
|
|
|
|
## try to preper stop (have signal handler):
|
|
|
|
|
os.kill(pid, signal.SIGTERM)
|
|
|
|
|
## check still exists after small timeout:
|
|
|
|
|
if not Utils.wait_for(lambda: not _pid_exists(pid), MAX_WAITTIME / 3):
|
|
|
|
|
## try to kill hereafter:
|
|
|
|
|
os.kill(pid, signal.SIGKILL)
|
|
|
|
|
return not _pid_exists(pid)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
sysLog.debug(e)
|
|
|
|
|
finally:
|
|
|
|
|
if f is not None:
|
|
|
|
|
f.close()
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Fail2banClientTest(LogCaptureTestCase):
|
|
|
|
|
|
|
|
|
@ -188,126 +231,144 @@ class Fail2banClientTest(LogCaptureTestCase):
|
|
|
|
|
|
|
|
|
|
@withtmpdir
|
|
|
|
|
def testClientStartBackgroundInside(self, tmp):
|
|
|
|
|
# always add "--async" by start inside, should don't fork by async (not replace client with server, just start in new process)
|
|
|
|
|
# (we can't fork the test cases process):
|
|
|
|
|
startparams = _start_params(tmp, True)
|
|
|
|
|
# start:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT, "--async", "-b") + startparams + ("start",))
|
|
|
|
|
self.assertLogged("Server ready")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
try:
|
|
|
|
|
# always add "--async" by start inside, should don't fork by async (not replace client with server, just start in new process)
|
|
|
|
|
# (we can't fork the test cases process):
|
|
|
|
|
startparams = _start_params(tmp, True)
|
|
|
|
|
# start:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
self.assertRaises(FailExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("~~unknown~cmd~failed~~",))
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("stop",))
|
|
|
|
|
self.assertLogged("Shutdown successful")
|
|
|
|
|
(CLIENT, "--async", "-b") + startparams + ("start",))
|
|
|
|
|
self.assertLogged("Server ready")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
try:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
self.assertRaises(FailExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("~~unknown~cmd~failed~~",))
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("stop",))
|
|
|
|
|
self.assertLogged("Shutdown successful")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
finally:
|
|
|
|
|
_kill_srv(tmp)
|
|
|
|
|
|
|
|
|
|
@withtmpdir
|
|
|
|
|
def testClientStartBackgroundCall(self, tmp):
|
|
|
|
|
global INTERACT
|
|
|
|
|
startparams = _start_params(tmp)
|
|
|
|
|
# start (without async in new process):
|
|
|
|
|
cmd = os.path.join(os.path.join(BIN), CLIENT)
|
|
|
|
|
logSys.debug('Start %s ...', cmd)
|
|
|
|
|
Utils.executeCmd((cmd,) + startparams + ("start",),
|
|
|
|
|
timeout=MAX_WAITTIME, shell=False, output=False)
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
try:
|
|
|
|
|
# echo from client (inside):
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
self.assertLogged("TEST-ECHO")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# interactive client chat with started server:
|
|
|
|
|
INTERACT += [
|
|
|
|
|
"echo INTERACT-ECHO",
|
|
|
|
|
"status",
|
|
|
|
|
"exit"
|
|
|
|
|
]
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("-i",))
|
|
|
|
|
self.assertLogged("INTERACT-ECHO")
|
|
|
|
|
self.assertLogged("Status", "Number of jail:")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# test reload and restart over interactive client:
|
|
|
|
|
INTERACT += [
|
|
|
|
|
"reload",
|
|
|
|
|
"restart",
|
|
|
|
|
"exit"
|
|
|
|
|
]
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("-i",))
|
|
|
|
|
self.assertLogged("Reading config files:")
|
|
|
|
|
self.assertLogged("Shutdown successful")
|
|
|
|
|
self.assertLogged("Server ready")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
global INTERACT
|
|
|
|
|
startparams = _start_params(tmp)
|
|
|
|
|
# start (without async in new process):
|
|
|
|
|
cmd = os.path.join(os.path.join(BIN), CLIENT)
|
|
|
|
|
logSys.debug('Start %s ...', cmd)
|
|
|
|
|
Utils.executeCmd((cmd,) + startparams + ("start",),
|
|
|
|
|
timeout=MAX_WAITTIME, shell=False, output=False)
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
try:
|
|
|
|
|
# echo from client (inside):
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
self.assertLogged("TEST-ECHO")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# interactive client chat with started server:
|
|
|
|
|
INTERACT += [
|
|
|
|
|
"echo INTERACT-ECHO",
|
|
|
|
|
"status",
|
|
|
|
|
"exit"
|
|
|
|
|
]
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("-i",))
|
|
|
|
|
self.assertLogged("INTERACT-ECHO")
|
|
|
|
|
self.assertLogged("Status", "Number of jail:")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# test reload and restart over interactive client:
|
|
|
|
|
INTERACT += [
|
|
|
|
|
"reload",
|
|
|
|
|
"restart",
|
|
|
|
|
"exit"
|
|
|
|
|
]
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("-i",))
|
|
|
|
|
self.assertLogged("Reading config files:")
|
|
|
|
|
self.assertLogged("Shutdown successful")
|
|
|
|
|
self.assertLogged("Server ready")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("stop",))
|
|
|
|
|
self.assertLogged("Shutdown successful")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("stop",))
|
|
|
|
|
self.assertLogged("Shutdown successful")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
_kill_srv(tmp)
|
|
|
|
|
|
|
|
|
|
def _testClientStartForeground(self, tmp, startparams, phase):
|
|
|
|
|
# start and wait to end (foreground):
|
|
|
|
|
logSys.debug("-- start of test worker")
|
|
|
|
|
phase['start'] = True
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT, "-f") + startparams + ("start",))
|
|
|
|
|
# end :
|
|
|
|
|
phase['end'] = True
|
|
|
|
|
logSys.debug("-- end of test worker")
|
|
|
|
|
|
|
|
|
|
@withtmpdir
|
|
|
|
|
def testClientStartForeground(self, tmp):
|
|
|
|
|
# started directly here, so prevent overwrite test cases logger with "INHERITED"
|
|
|
|
|
startparams = _start_params(tmp, logtarget="INHERITED")
|
|
|
|
|
# because foreground block execution - start it in thread:
|
|
|
|
|
phase = dict()
|
|
|
|
|
Thread(name="_TestCaseWorker",
|
|
|
|
|
target=Fail2banClientTest._testClientStartForeground, args=(self, tmp, startparams, phase)).start()
|
|
|
|
|
th = None
|
|
|
|
|
try:
|
|
|
|
|
# wait for start thread:
|
|
|
|
|
Utils.wait_for(lambda: phase.get('start', None) is not None, MAX_WAITTIME)
|
|
|
|
|
self.assertTrue(phase.get('start', None))
|
|
|
|
|
# wait for server (socket):
|
|
|
|
|
Utils.wait_for(lambda: os.path.exists(tmp+"/f2b.sock"), MAX_WAITTIME)
|
|
|
|
|
self.assertLogged("Starting communication")
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("ping",))
|
|
|
|
|
self.assertRaises(FailExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("~~unknown~cmd~failed~~",))
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
# started directly here, so prevent overwrite test cases logger with "INHERITED"
|
|
|
|
|
startparams = _start_params(tmp, logtarget="INHERITED")
|
|
|
|
|
# because foreground block execution - start it in thread:
|
|
|
|
|
phase = dict()
|
|
|
|
|
th = Thread(name="_TestCaseWorker",
|
|
|
|
|
target=Fail2banClientTest._testClientStartForeground, args=(self, tmp, startparams, phase))
|
|
|
|
|
th.daemon = True
|
|
|
|
|
th.start()
|
|
|
|
|
try:
|
|
|
|
|
# wait for start thread:
|
|
|
|
|
Utils.wait_for(lambda: phase.get('start', None) is not None, MAX_WAITTIME)
|
|
|
|
|
self.assertTrue(phase.get('start', None))
|
|
|
|
|
# wait for server (socket):
|
|
|
|
|
Utils.wait_for(lambda: os.path.exists(tmp+"/f2b.sock"), MAX_WAITTIME)
|
|
|
|
|
self.assertLogged("Starting communication")
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("ping",))
|
|
|
|
|
self.assertRaises(FailExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("~~unknown~cmd~failed~~",))
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("stop",))
|
|
|
|
|
# wait for end:
|
|
|
|
|
Utils.wait_for(lambda: phase.get('end', None) is not None, MAX_WAITTIME)
|
|
|
|
|
self.assertTrue(phase.get('end', None))
|
|
|
|
|
self.assertLogged("Shutdown successful", "Exiting Fail2ban")
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_client,
|
|
|
|
|
(CLIENT,) + startparams + ("stop",))
|
|
|
|
|
# wait for end:
|
|
|
|
|
Utils.wait_for(lambda: phase.get('end', None) is not None, MAX_WAITTIME)
|
|
|
|
|
self.assertTrue(phase.get('end', None))
|
|
|
|
|
self.assertLogged("Shutdown successful", "Exiting Fail2ban")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
_kill_srv(tmp)
|
|
|
|
|
if th:
|
|
|
|
|
th.join()
|
|
|
|
|
|
|
|
|
|
@withtmpdir
|
|
|
|
|
def testClientFailStart(self, tmp):
|
|
|
|
|
self.assertRaises(FailExitException, _exec_client,
|
|
|
|
|
(CLIENT, "--async", "-c", tmp+"/miss", "start",))
|
|
|
|
|
self.assertLogged("Base configuration directory " + tmp+"/miss" + " does not exist")
|
|
|
|
|
try:
|
|
|
|
|
self.assertRaises(FailExitException, _exec_client,
|
|
|
|
|
(CLIENT, "--async", "-c", tmp+"/miss", "start",))
|
|
|
|
|
self.assertLogged("Base configuration directory " + tmp+"/miss" + " does not exist")
|
|
|
|
|
|
|
|
|
|
self.assertRaises(FailExitException, _exec_client,
|
|
|
|
|
(CLIENT, "--async", "-c", CONF_DIR, "-s", tmp+"/miss/f2b.sock", "start",))
|
|
|
|
|
self.assertLogged("There is no directory " + tmp+"/miss" + " to contain the socket file")
|
|
|
|
|
self.assertRaises(FailExitException, _exec_client,
|
|
|
|
|
(CLIENT, "--async", "-c", CONF_DIR, "-s", tmp+"/miss/f2b.sock", "start",))
|
|
|
|
|
self.assertLogged("There is no directory " + tmp+"/miss" + " to contain the socket file")
|
|
|
|
|
finally:
|
|
|
|
|
_kill_srv(tmp)
|
|
|
|
|
|
|
|
|
|
def testVisualWait(self):
|
|
|
|
|
sleeptime = 0.035
|
|
|
|
@ -339,73 +400,89 @@ class Fail2banServerTest(LogCaptureTestCase):
|
|
|
|
|
|
|
|
|
|
@withtmpdir
|
|
|
|
|
def testServerStartBackground(self, tmp):
|
|
|
|
|
# don't add "--async" by start, because if will fork current process by daemonize
|
|
|
|
|
# (we can't fork the test cases process),
|
|
|
|
|
# because server started internal communication in new thread use INHERITED as logtarget here:
|
|
|
|
|
startparams = _start_params(tmp, logtarget="INHERITED")
|
|
|
|
|
# start:
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER, "-b") + startparams)
|
|
|
|
|
self.assertLogged("Server ready")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
try:
|
|
|
|
|
# don't add "--async" by start, because if will fork current process by daemonize
|
|
|
|
|
# (we can't fork the test cases process),
|
|
|
|
|
# because server started internal communication in new thread use INHERITED as logtarget here:
|
|
|
|
|
startparams = _start_params(tmp, logtarget="INHERITED")
|
|
|
|
|
# start:
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
self.assertRaises(FailExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("~~unknown~cmd~failed~~",))
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("stop",))
|
|
|
|
|
self.assertLogged("Shutdown successful")
|
|
|
|
|
(SERVER, "-b") + startparams)
|
|
|
|
|
self.assertLogged("Server ready")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
try:
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
self.assertRaises(FailExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("~~unknown~cmd~failed~~",))
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("stop",))
|
|
|
|
|
self.assertLogged("Shutdown successful")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
finally:
|
|
|
|
|
_kill_srv(tmp)
|
|
|
|
|
|
|
|
|
|
def _testServerStartForeground(self, tmp, startparams, phase):
|
|
|
|
|
# start and wait to end (foreground):
|
|
|
|
|
logSys.debug("-- start of test worker")
|
|
|
|
|
phase['start'] = True
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER, "-f") + startparams + ("start",))
|
|
|
|
|
# end :
|
|
|
|
|
phase['end'] = True
|
|
|
|
|
logSys.debug("-- end of test worker")
|
|
|
|
|
|
|
|
|
|
@withtmpdir
|
|
|
|
|
def testServerStartForeground(self, tmp):
|
|
|
|
|
# started directly here, so prevent overwrite test cases logger with "INHERITED"
|
|
|
|
|
startparams = _start_params(tmp, logtarget="INHERITED")
|
|
|
|
|
# because foreground block execution - start it in thread:
|
|
|
|
|
phase = dict()
|
|
|
|
|
Thread(name="_TestCaseWorker",
|
|
|
|
|
target=Fail2banServerTest._testServerStartForeground, args=(self, tmp, startparams, phase)).start()
|
|
|
|
|
th = None
|
|
|
|
|
try:
|
|
|
|
|
# wait for start thread:
|
|
|
|
|
Utils.wait_for(lambda: phase.get('start', None) is not None, MAX_WAITTIME)
|
|
|
|
|
self.assertTrue(phase.get('start', None))
|
|
|
|
|
# wait for server (socket):
|
|
|
|
|
Utils.wait_for(lambda: os.path.exists(tmp+"/f2b.sock"), MAX_WAITTIME)
|
|
|
|
|
self.assertLogged("Starting communication")
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("ping",))
|
|
|
|
|
self.assertRaises(FailExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("~~unknown~cmd~failed~~",))
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
# started directly here, so prevent overwrite test cases logger with "INHERITED"
|
|
|
|
|
startparams = _start_params(tmp, logtarget="INHERITED")
|
|
|
|
|
# because foreground block execution - start it in thread:
|
|
|
|
|
phase = dict()
|
|
|
|
|
th = Thread(name="_TestCaseWorker",
|
|
|
|
|
target=Fail2banServerTest._testServerStartForeground, args=(self, tmp, startparams, phase))
|
|
|
|
|
th.daemon = True
|
|
|
|
|
th.start()
|
|
|
|
|
try:
|
|
|
|
|
# wait for start thread:
|
|
|
|
|
Utils.wait_for(lambda: phase.get('start', None) is not None, MAX_WAITTIME)
|
|
|
|
|
self.assertTrue(phase.get('start', None))
|
|
|
|
|
# wait for server (socket):
|
|
|
|
|
Utils.wait_for(lambda: os.path.exists(tmp+"/f2b.sock"), MAX_WAITTIME)
|
|
|
|
|
self.assertLogged("Starting communication")
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("ping",))
|
|
|
|
|
self.assertRaises(FailExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("~~unknown~cmd~failed~~",))
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("echo", "TEST-ECHO",))
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("stop",))
|
|
|
|
|
# wait for end:
|
|
|
|
|
Utils.wait_for(lambda: phase.get('end', None) is not None, MAX_WAITTIME)
|
|
|
|
|
self.assertTrue(phase.get('end', None))
|
|
|
|
|
self.assertLogged("Shutdown successful", "Exiting Fail2ban")
|
|
|
|
|
finally:
|
|
|
|
|
self.pruneLog()
|
|
|
|
|
# stop:
|
|
|
|
|
self.assertRaises(ExitException, _exec_server,
|
|
|
|
|
(SERVER,) + startparams + ("stop",))
|
|
|
|
|
# wait for end:
|
|
|
|
|
Utils.wait_for(lambda: phase.get('end', None) is not None, MAX_WAITTIME)
|
|
|
|
|
self.assertTrue(phase.get('end', None))
|
|
|
|
|
self.assertLogged("Shutdown successful", "Exiting Fail2ban")
|
|
|
|
|
self.assertLogged("Exit with code 0")
|
|
|
|
|
_kill_srv(tmp)
|
|
|
|
|
if th:
|
|
|
|
|
th.join()
|
|
|
|
|
|
|
|
|
|
@withtmpdir
|
|
|
|
|
def testServerFailStart(self, tmp):
|
|
|
|
|
self.assertRaises(FailExitException, _exec_server,
|
|
|
|
|
(SERVER, "-c", tmp+"/miss",))
|
|
|
|
|
self.assertLogged("Base configuration directory " + tmp+"/miss" + " does not exist")
|
|
|
|
|
try:
|
|
|
|
|
self.assertRaises(FailExitException, _exec_server,
|
|
|
|
|
(SERVER, "-c", tmp+"/miss",))
|
|
|
|
|
self.assertLogged("Base configuration directory " + tmp+"/miss" + " does not exist")
|
|
|
|
|
|
|
|
|
|
self.assertRaises(FailExitException, _exec_server,
|
|
|
|
|
(SERVER, "-c", CONF_DIR, "-s", tmp+"/miss/f2b.sock",))
|
|
|
|
|
self.assertLogged("There is no directory " + tmp+"/miss" + " to contain the socket file")
|
|
|
|
|
self.assertRaises(FailExitException, _exec_server,
|
|
|
|
|
(SERVER, "-c", CONF_DIR, "-s", tmp+"/miss/f2b.sock",))
|
|
|
|
|
self.assertLogged("There is no directory " + tmp+"/miss" + " to contain the socket file")
|
|
|
|
|
finally:
|
|
|
|
|
_kill_srv(tmp)
|
|
|
|
|