From 2a98b06c70c93c63298ac0cc5402a74d8015f40b Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Tue, 29 Nov 2022 12:57:19 +0800 Subject: [PATCH 1/2] nm: Fix activation retry Using `time.sleep(5)` will not process the MainLoop of NM library which will cause checkpoint expire during `time.sleep()`. Use Glib timer will fix this problem. Integration test case created to create 32 veth in single transaction, the test case is marked as slow as it takes 10 seconds to finish. Signed-off-by: Gris Ge --- libnmstate/nm/active_connection.py | 38 +++++++++++++++++------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/libnmstate/nm/active_connection.py b/libnmstate/nm/active_connection.py index 66e82aec..4c0ef9d5 100644 --- a/libnmstate/nm/active_connection.py +++ b/libnmstate/nm/active_connection.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2019-2020 Red Hat, Inc. +# Copyright (c) 2019-2022 Red Hat, Inc. # # This file is part of nmstate # @@ -17,7 +17,6 @@ # along with this program. If not, see . # -import time import logging from libnmstate.error import NmstateLibnmError @@ -105,6 +104,19 @@ class ProfileActivation: self._fallback_checker = None self._fallback_checker_counter = 0 + def _retry_activate(self, _user_data): + specific_object = None + retried = True + self._ctx.client.activate_connection_async( + self._nm_profile, + self._nm_dev, + specific_object, + self._ctx.cancellable, + self._activate_profile_callback, + retried, + ) + return GLib.SOURCE_REMOVE + def run(self): specific_object = None self._action = ( @@ -112,7 +124,7 @@ class ProfileActivation: f"iface:{self._iface_name} type: {self._iface_type}" ) - retry = True + retried = False self._ctx.register_async(self._action) self._ctx.client.activate_connection_async( self._nm_profile, @@ -120,7 +132,7 @@ class ProfileActivation: specific_object, self._ctx.cancellable, self._activate_profile_callback, - retry, + retried, ) self._fallback_checker = GLib.timeout_source_new( FALLBACK_CHECKER_INTERNAL * 1000 @@ -154,7 +166,7 @@ class ProfileActivation: activation._fallback_checker.attach(ctx.context) activation._wait_profile_activation() - def _activate_profile_callback(self, nm_client, result, retry): + def _activate_profile_callback(self, nm_client, result, retried): nm_ac = None if self._ctx.is_cancelled(): self._activation_clean_up() @@ -162,22 +174,16 @@ class ProfileActivation: try: nm_ac = nm_client.activate_connection_finish(result) except GLib.Error as e: - if retry: - retry = False - specific_object = None + if not retried: logging.debug( f"Action {self._action} failed, trying again in " f"{ACTIVATION_RETRY_SLEEP} seconds." ) - time.sleep(ACTIVATION_RETRY_SLEEP) - self._ctx.client.activate_connection_async( - self._nm_profile, - self._nm_dev, - specific_object, - self._ctx.cancellable, - self._activate_profile_callback, - retry, + activation_retry_timer = GLib.timeout_source_new( + ACTIVATION_RETRY_SLEEP * 1000 ) + activation_retry_timer.set_callback(self._retry_activate, None) + activation_retry_timer.attach(self._ctx.context) return elif e.matches(Gio.io_error_quark(), Gio.IOErrorEnum.TIMED_OUT): logging.debug( -- 2.38.1 From 70c4a665aa6341c8bf22e2a91749bd8ae551b2b7 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Tue, 6 Dec 2022 16:12:21 +0800 Subject: [PATCH 2/2] nm: Fix `time.sleep()` in `_import_current_device()` The `time.sleep()` in `_import_current_device()` will cause checkpoint timeout as the `time.sleep()` does not iterate the NM Mainloop which cause the checkpoint refresh not function as expected. Invoking a `NmContext.refresh()` after every small `time.sleep()` fixed this problem. Extra test case not required, this problem only found on slow server(my VM compiling rust project at the same time). Signed-off-by: Gris Ge --- libnmstate/nm/profile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libnmstate/nm/profile.py b/libnmstate/nm/profile.py index 82643d73..85c0e623 100644 --- a/libnmstate/nm/profile.py +++ b/libnmstate/nm/profile.py @@ -501,6 +501,7 @@ class NmProfile: break else: time.sleep(IMPORT_NM_DEV_RETRY_INTERNAL) + self._ctx.refresh() def import_current(self): self._nm_dev = get_nm_dev( -- 2.38.1