diff --git a/src/charm.py b/src/charm.py index 47ccdd351..13d941151 100755 --- a/src/charm.py +++ b/src/charm.py @@ -276,9 +276,6 @@ def _on_config_changed(self, _) -> None: # the upgrade already restart the daemon return - # restart not required if mysqld is not running - mysqld_running = self._mysql.is_mysqld_running() - previous_config = self.mysql_config.custom_config if not previous_config: # empty config means not initialized, skipping @@ -298,30 +295,33 @@ def _on_config_changed(self, _) -> None: changed_config = compare_dictionaries(previous_config, new_config_dict) - if self.mysql_config.keys_requires_restart(changed_config): - # there are static configurations in changed keys - logger.info("Persisting configuration changes to file") - # persist config to file - self._mysql.write_content_to_file( - path=MYSQLD_CUSTOM_CONFIG_FILE, content=new_config_content - ) - if mysqld_running: - logger.info("Configuration change requires restart") + logger.info("Persisting configuration changes to file") + # always persist config to file + self._mysql.write_content_to_file( + path=MYSQLD_CUSTOM_CONFIG_FILE, content=new_config_content + ) - if "loose-audit_log_format" in changed_config: - # plugins are manipulated running daemon - if self.config.plugin_audit_enabled: - self._mysql.install_plugins(["audit_log", "audit_log_filter"]) - else: - self._mysql.uninstall_plugins(["audit_log", "audit_log_filter"]) + if ( + self.mysql_config.keys_requires_restart(changed_config) + and self._mysql.is_mysqld_running() + ): + logger.info("Configuration change requires restart") + if "loose-audit_log_format" in changed_config: + # plugins are manipulated on running daemon + if self.config.plugin_audit_enabled: + self._mysql.install_plugins(["audit_log", "audit_log_filter"]) + else: + self._mysql.uninstall_plugins(["audit_log", "audit_log_filter"]) - self.on[f"{self.restart.name}"].acquire_lock.emit() - return + self.on[f"{self.restart.name}"].acquire_lock.emit() - if dynamic_config := self.mysql_config.filter_static_keys(changed_config): + elif dynamic_config := self.mysql_config.filter_static_keys(changed_config): # if only dynamic config changed, apply it logger.info("Configuration does not requires restart") for config in dynamic_config: + if config not in new_config_dict: + # skip removed configs + continue self._mysql.set_dynamic_variable(config, new_config_dict[config]) def _on_start(self, event: StartEvent) -> None: diff --git a/tests/integration/high_availability/test_upgrade_skip_pre_upgrade_check.py b/tests/integration/high_availability/test_upgrade_skip_pre_upgrade_check.py index b0a0a121b..e53c8fdfd 100644 --- a/tests/integration/high_availability/test_upgrade_skip_pre_upgrade_check.py +++ b/tests/integration/high_availability/test_upgrade_skip_pre_upgrade_check.py @@ -3,6 +3,7 @@ import asyncio import logging +import subprocess from time import sleep import pytest @@ -71,7 +72,37 @@ async def test_refresh_without_pre_upgrade_check(ops_test: OpsTest): # 2. Rolling restart, if there's a configuration change # for both, operations should continue to work # and there's a mismatch between the charm and the snap - logger.info("Wait for rolling restart OR continue to writes") + logger.info("Wait (120s) for rolling restart OR continue to writes") + count = 0 + while count < 2 * 60: + if "maintenance" in {unit.workload_status for unit in application.units}: + # Case when refresh triggers a rolling restart + logger.info("Waiting for rolling restart to complete") + await ops_test.model.wait_for_idle( + apps=[MYSQL_APP_NAME], status="active", idle_period=30, timeout=TIMEOUT + ) + break + else: + count += 1 + sleep(1) + + await ensure_all_units_continuous_writes_incrementing(ops_test) + + +@pytest.mark.group(1) +@markers.amd64_only # TODO: remove after arm64 stable release +async def test_rollback_without_pre_upgrade_check(ops_test: OpsTest): + """Test refresh back to stable channel.""" + application = ops_test.model.applications[MYSQL_APP_NAME] + + logger.info("Refresh the charm back to stable channel") + # pylibjuju refresh dont work for switch: + # https://github.com/juju/python-libjuju/issues/924 + subprocess.check_output( + f"juju refresh {MYSQL_APP_NAME} --switch ch:{MYSQL_APP_NAME} --channel 8.0/stable".split() + ) + + logger.info("Wait (120s) for rolling restart OR continue to writes") count = 0 while count < 2 * 60: if "maintenance" in {unit.workload_status for unit in application.units}: @@ -85,5 +116,4 @@ async def test_refresh_without_pre_upgrade_check(ops_test: OpsTest): count += 1 sleep(1) - logger.info("Ensure continuous_writes") await ensure_all_units_continuous_writes_incrementing(ops_test)