From 8b02af34541292212fc42323828af3bad1190726 Mon Sep 17 00:00:00 2001 From: "Heindl, Lukas" <191340695+Lukas-Heindl@users.noreply.github.com> Date: Fri, 11 Apr 2025 10:54:11 +0200 Subject: [PATCH 1/9] fixes certtools/intelmq#2595 retry multiple times on `intelmqctl stop` to check if bots really stopped, since the bots might take longer to stop. Using retry in constrast to increasing the sleep_time keeps the delay short in case the bots did already stop. --- intelmq/bin/intelmqctl.py | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/intelmq/bin/intelmqctl.py b/intelmq/bin/intelmqctl.py index 91a0ec9420..ce7cd0164f 100644 --- a/intelmq/bin/intelmqctl.py +++ b/intelmq/bin/intelmqctl.py @@ -563,12 +563,36 @@ def botnet_stop(self, group=None): for bot_id in bots: self.bot_stop(bot_id, getstatus=False) - retval = 0 - time.sleep(0.75) - for bot_id in bots: - botnet_status[bot_id] = self.bot_status(bot_id)[1] - if botnet_status[bot_id] not in ['stopped', 'disabled']: - retval = 1 + # shallow copy of the list suffices + # only aliasing the list to ease reading the following + stopped_but_still_running_bots = bots + + # parameters: + # - sleep 0.75 s with an increment of 0.1 + # - at most 5 tries + # => sleep-ing at most 4.75 seconds + sleep_time = 0.75 # in seconds + for _ in range(5): + # give the bots some time to terminate + time.sleep(sleep_time) + # update the botnet_status + for bot_id in stopped_but_still_running_bots: + botnet_status[bot_id] = self.bot_status(bot_id)[1] + if botnet_status[bot_id] in ['stopped', 'disabled']: + stopped_but_still_running_bots.remove(bot_id) + + # check if all bots are stopped -> no need to wait further + if len(stopped_but_still_running_bots) == 0: + break + # the longer the bots need to terminate the longer we wait to check + # again to avoid long-term load on the system + # but stop at 5 seconds to avoid waiting too long until rechecking + # the status + sleep_time = min(5, sleep_time+0.1) + + retval = 1 + if len(stopped_but_still_running_bots) == 0: + retval = 0 self.log_botnet_message('stopped', group) return retval, botnet_status From 309f868066783c4f04843d0f7becad3ba79eb5b7 Mon Sep 17 00:00:00 2001 From: "Heindl, Lukas" <191340695+Lukas-Heindl@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:07:43 +0200 Subject: [PATCH 2/9] make amount of retries configurable --- intelmq/bin/intelmqctl.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/intelmq/bin/intelmqctl.py b/intelmq/bin/intelmqctl.py index ce7cd0164f..1bcd4f4815 100644 --- a/intelmq/bin/intelmqctl.py +++ b/intelmq/bin/intelmqctl.py @@ -567,12 +567,14 @@ def botnet_stop(self, group=None): # only aliasing the list to ease reading the following stopped_but_still_running_bots = bots - # parameters: + retries = getattr(self._parameters, 'stop_retry_limit', 5) + + # parameters (default): # - sleep 0.75 s with an increment of 0.1 # - at most 5 tries # => sleep-ing at most 4.75 seconds sleep_time = 0.75 # in seconds - for _ in range(5): + for _ in range(retries): # give the bots some time to terminate time.sleep(sleep_time) # update the botnet_status From e51040e9f0cf7a9da2ee75a6d670d0a7084a614e Mon Sep 17 00:00:00 2001 From: "Heindl, Lukas" <191340695+Lukas-Heindl@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:08:01 +0200 Subject: [PATCH 3/9] document new config parameter --- docs/admin/configuration/intelmq.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/admin/configuration/intelmq.md b/docs/admin/configuration/intelmq.md index c82bb08fe5..941722f849 100644 --- a/docs/admin/configuration/intelmq.md +++ b/docs/admin/configuration/intelmq.md @@ -237,6 +237,13 @@ configured to do so. (optional, boolean) Verify the TLS certificate of the server. Defaults to true. +**`stop_retry_limit`** + +(optional, integer) amount of retries when checking the status of a botnet after issuing `intelmqctl stop`. Each retry +another *0.1s* longer is waited until a maximum of *5s* to sleep in each iteration is reached. Only applies when +stopping a bot*net* (not individual bots). +Defaults to 5. + #### Individual Bot Configuration !!! info From 4ae7c857fe3da928326581c28a16ea773418d5b0 Mon Sep 17 00:00:00 2001 From: "Heindl, Lukas" <191340695+Lukas-Heindl@users.noreply.github.com> Date: Thu, 17 Apr 2025 11:02:53 +0200 Subject: [PATCH 4/9] formatting changes --- intelmq/bin/intelmqctl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intelmq/bin/intelmqctl.py b/intelmq/bin/intelmqctl.py index 1bcd4f4815..7aae02b2bf 100644 --- a/intelmq/bin/intelmqctl.py +++ b/intelmq/bin/intelmqctl.py @@ -573,7 +573,7 @@ def botnet_stop(self, group=None): # - sleep 0.75 s with an increment of 0.1 # - at most 5 tries # => sleep-ing at most 4.75 seconds - sleep_time = 0.75 # in seconds + sleep_time = 0.75 # in seconds for _ in range(retries): # give the bots some time to terminate time.sleep(sleep_time) @@ -590,7 +590,7 @@ def botnet_stop(self, group=None): # again to avoid long-term load on the system # but stop at 5 seconds to avoid waiting too long until rechecking # the status - sleep_time = min(5, sleep_time+0.1) + sleep_time = min(5, sleep_time + 0.1) retval = 1 if len(stopped_but_still_running_bots) == 0: From 0d3417a83e0fa4ca1ea5c35cb1779c91d1f8472e Mon Sep 17 00:00:00 2001 From: Lukas-Heindl <191340695+Lukas-Heindl@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:19:52 +0200 Subject: [PATCH 5/9] Update intelmq/bin/intelmqctl.py Co-authored-by: Sebastian --- intelmq/bin/intelmqctl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intelmq/bin/intelmqctl.py b/intelmq/bin/intelmqctl.py index 7aae02b2bf..6fc94dd437 100644 --- a/intelmq/bin/intelmqctl.py +++ b/intelmq/bin/intelmqctl.py @@ -584,7 +584,7 @@ def botnet_stop(self, group=None): stopped_but_still_running_bots.remove(bot_id) # check if all bots are stopped -> no need to wait further - if len(stopped_but_still_running_bots) == 0: + if not stopped_but_still_running_bots: break # the longer the bots need to terminate the longer we wait to check # again to avoid long-term load on the system From 7a32035a0668d9aea82a47833622942eb234f663 Mon Sep 17 00:00:00 2001 From: "Heindl, Lukas" <191340695+Lukas-Heindl@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:40:08 +0200 Subject: [PATCH 6/9] fix mistake in removing within the loop --- intelmq/bin/intelmqctl.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/intelmq/bin/intelmqctl.py b/intelmq/bin/intelmqctl.py index 6fc94dd437..11fabaab65 100644 --- a/intelmq/bin/intelmqctl.py +++ b/intelmq/bin/intelmqctl.py @@ -578,10 +578,11 @@ def botnet_stop(self, group=None): # give the bots some time to terminate time.sleep(sleep_time) # update the botnet_status - for bot_id in stopped_but_still_running_bots: - botnet_status[bot_id] = self.bot_status(bot_id)[1] - if botnet_status[bot_id] in ['stopped', 'disabled']: - stopped_but_still_running_bots.remove(bot_id) + # only keep bots in the list which are not stopped already + stopped_but_still_running_bots = list(filter( + lambda bot_id: self.bot_status(bot_id)[1] not in ['stopped', 'disabled'], + stopped_but_still_running_bots + )) # check if all bots are stopped -> no need to wait further if not stopped_but_still_running_bots: From 7f406cac18ca8b96d235d3293f9aecdd82f3fd98 Mon Sep 17 00:00:00 2001 From: "Heindl, Lukas" <191340695+Lukas-Heindl@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:16:45 +0200 Subject: [PATCH 7/9] filter -> list comprehension --- intelmq/bin/intelmqctl.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/intelmq/bin/intelmqctl.py b/intelmq/bin/intelmqctl.py index 11fabaab65..c0c9e6fc52 100644 --- a/intelmq/bin/intelmqctl.py +++ b/intelmq/bin/intelmqctl.py @@ -579,10 +579,11 @@ def botnet_stop(self, group=None): time.sleep(sleep_time) # update the botnet_status # only keep bots in the list which are not stopped already - stopped_but_still_running_bots = list(filter( - lambda bot_id: self.bot_status(bot_id)[1] not in ['stopped', 'disabled'], - stopped_but_still_running_bots - )) + stopped_but_still_running_bots = [ + bot_id + for bot_id in stopped_but_still_running_bots + if self.bot_status(bot_id)[1] not in ['stopped', 'disabled'] + ] # check if all bots are stopped -> no need to wait further if not stopped_but_still_running_bots: From 976ccf4e76236b4fa2de9450b694bb96a4b050aa Mon Sep 17 00:00:00 2001 From: "Heindl, Lukas" <191340695+Lukas-Heindl@users.noreply.github.com> Date: Mon, 18 Aug 2025 16:21:50 +0200 Subject: [PATCH 8/9] fix wrong returned botnet_status --- intelmq/bin/intelmqctl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/intelmq/bin/intelmqctl.py b/intelmq/bin/intelmqctl.py index c0c9e6fc52..35d5e8716c 100644 --- a/intelmq/bin/intelmqctl.py +++ b/intelmq/bin/intelmqctl.py @@ -578,11 +578,13 @@ def botnet_stop(self, group=None): # give the bots some time to terminate time.sleep(sleep_time) # update the botnet_status + for bot_id in stopped_but_still_running_bots: + botnet_status[bot_id] = self.bot_status(bot_id)[1] # only keep bots in the list which are not stopped already stopped_but_still_running_bots = [ bot_id for bot_id in stopped_but_still_running_bots - if self.bot_status(bot_id)[1] not in ['stopped', 'disabled'] + if botnet_status[bot_id] not in ['stopped', 'disabled'] ] # check if all bots are stopped -> no need to wait further From fb92b9c8f6bf7fac594a57bcc1901554b5b1fb75 Mon Sep 17 00:00:00 2001 From: Sebastian Wagner Date: Mon, 18 Aug 2025 21:19:40 +0200 Subject: [PATCH 9/9] doc: changelog for PR#2598 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dac3ac20e1..e994ad8882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,13 @@ Please refer to the [NEWS](NEWS.md) for a list of changes which have an affect o -------------------------------- ### Configuration +- New parameter `stop_retry_limit` (PR#2598 by Lukas Heindl). ### Core - Drop support for Python 3.8 (fixes #2616, PR#2617 by Sebastian Wagner). - `intelmq.lib.splitreports`: Handle bot parameter `chunk_size` values empty string, due to missing parameter typing checks (PR#2604 by Sebastian Wagner). - `intelmq.lib.mixins.sql` Add Support for MySQL (PR#2625 by Karl-Johan Karlsson). +- New parameter `stop_retry_limit` to gracefully handle stopping bots which take longer to shutdown (PR#2598 by Lukas Heindl, fixes #2595). ### Development