Skip to content

Commit ce8687c

Browse files
authored
DPE-5582 Timeout node count query (#514)
* lib bump * timeout for node count retrieval * add method required by lib update * remove unstable flag * fix test after change in log level * allow idle state detection
1 parent 3c78175 commit ce8687c

File tree

6 files changed

+51
-14
lines changed

6 files changed

+51
-14
lines changed

lib/charms/mysql/v0/mysql.py

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def wait_until_mysql_connection(self) -> None:
134134
# Increment this major API version when introducing breaking changes
135135
LIBAPI = 0
136136

137-
LIBPATCH = 73
137+
LIBPATCH = 75
138138

139139
UNIT_TEARDOWN_LOCKNAME = "unit-teardown"
140140
UNIT_ADD_LOCKNAME = "unit-add"
@@ -1085,16 +1085,25 @@ def configure_mysql_users(self, password_needed: bool = True) -> None:
10851085
)
10861086
raise MySQLConfigureMySQLUsersError(e.message)
10871087

1088+
def _plugin_file_exists(self, plugin_file_name: str) -> bool:
1089+
"""Check if the plugin file exists.
1090+
1091+
Args:
1092+
plugin_file_name: Plugin file name, with the extension.
1093+
1094+
"""
1095+
path = self.get_variable_value("plugin_dir")
1096+
return self._file_exists(f"{path}/{plugin_file_name}")
1097+
10881098
def install_plugins(self, plugins: list[str]) -> None:
10891099
"""Install extra plugins."""
10901100
supported_plugins = {
1091-
"audit_log": "INSTALL PLUGIN audit_log SONAME 'audit_log.so';",
1092-
"audit_log_filter": "INSTALL PLUGIN audit_log_filter SONAME 'audit_log_filter.so';",
1101+
"audit_log": ("INSTALL PLUGIN audit_log SONAME", "audit_log.so"),
1102+
"audit_log_filter": ("INSTALL PLUGIN audit_log_filter SONAME", "audit_log_filter.so"),
10931103
}
10941104

1095-
super_read_only = self.get_variable_value("super_read_only").lower() == "on"
1096-
10971105
try:
1106+
super_read_only = self.get_variable_value("super_read_only").lower() == "on"
10981107
installed_plugins = self._get_installed_plugins()
10991108
# disable super_read_only to install plugins
11001109
for plugin in plugins:
@@ -1106,7 +1115,16 @@ def install_plugins(self, plugins: list[str]) -> None:
11061115
logger.warning(f"{plugin=} is not supported")
11071116
continue
11081117

1109-
command = supported_plugins[plugin]
1118+
command_prefix, plugin_file = (
1119+
supported_plugins[plugin][0],
1120+
supported_plugins[plugin][1],
1121+
)
1122+
1123+
if not self._plugin_file_exists(plugin_file):
1124+
logger.warning(f"{plugin=} file not found. Skip installation")
1125+
continue
1126+
1127+
command = f"{command_prefix} '{plugin_file}';"
11101128
if super_read_only:
11111129
command = (
11121130
f"SET GLOBAL super_read_only=OFF; {command}"
@@ -1123,6 +1141,10 @@ def install_plugins(self, plugins: list[str]) -> None:
11231141
f"Failed to install {plugin=}", # type: ignore
11241142
)
11251143
raise MySQLPluginInstallError
1144+
except MySQLGetVariableError:
1145+
# workaround for config changed triggered after failed upgrade
1146+
# the check fails for charms revisions not using admin address
1147+
logger.warning("Failed to get super_read_only variable. Skip plugin installation")
11261148

11271149
def uninstall_plugins(self, plugins: list[str]) -> None:
11281150
"""Uninstall plugins."""
@@ -1915,7 +1937,7 @@ def get_cluster_node_count(
19151937
)
19161938

19171939
try:
1918-
output = self._run_mysqlsh_script("\n".join(size_commands))
1940+
output = self._run_mysqlsh_script("\n".join(size_commands), timeout=30)
19191941
except MySQLClientError:
19201942
logger.warning("Failed to get node count")
19211943
return 0
@@ -3147,3 +3169,12 @@ def _run_mysqlcli_script(
31473169
timeout: (optional) time before the query should timeout
31483170
"""
31493171
raise NotImplementedError
3172+
3173+
@abstractmethod
3174+
def _file_exists(self, path: str) -> bool:
3175+
"""Check if a file exists.
3176+
3177+
Args:
3178+
path: Path to the file to check
3179+
"""
3180+
raise NotImplementedError

src/mysql_k8s_helpers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,3 +812,11 @@ def set_cluster_primary(self, new_primary_address: str) -> None:
812812
def fetch_error_log(self) -> Optional[str]:
813813
"""Fetch the MySQL error log."""
814814
return self.read_file_content("/var/log/mysql/error.log")
815+
816+
def _file_exists(self, path: str) -> bool:
817+
"""Check if a file exists.
818+
819+
Args:
820+
path: Path to the file to check
821+
"""
822+
return self.container.exists(path)

tests/integration/high_availability/high_availability_helpers.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -495,10 +495,9 @@ async def ensure_all_units_continuous_writes_incrementing(
495495
)
496496

497497
async with ops_test.fast_forward(fast_interval="15s"):
498-
for attempt in Retrying(stop=stop_after_delay(15 * 60), wait=wait_fixed(10)):
499-
with attempt:
500-
# ensure that all units are up to date (including the previous primary)
501-
for unit in mysql_units:
498+
for unit in mysql_units:
499+
for attempt in Retrying(stop=stop_after_delay(15 * 60), wait=wait_fixed(10)):
500+
with attempt:
502501
# ensure the max written value is incrementing (continuous writes is active)
503502
max_written_value = await get_max_written_value_in_database(
504503
ops_test, unit, credentials

tests/integration/high_availability/test_node_drain.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ async def test_pod_eviction_and_pvc_deletion(
5555
delete_pvcs(primary_pod_pvcs)
5656
delete_pvs(primary_pod_pvs)
5757

58-
async with ops_test.fast_forward():
58+
async with ops_test.fast_forward("90s"):
5959
logger.info("Waiting for evicted primary pod to be rescheduled")
6060
await ops_test.model.wait_for_idle(
6161
apps=[mysql_application_name],

tests/integration/high_availability/test_self_healing.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ async def test_kill_db_process(
109109

110110
@pytest.mark.group(2)
111111
@pytest.mark.abort_on_fail
112-
@pytest.mark.unstable
113112
async def test_freeze_db_process(
114113
ops_test: OpsTest, highly_available_cluster, continuous_writes, credentials
115114
) -> None:

tests/integration/high_availability/test_upgrade_rollback_incompat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ async def test_upgrade_to_failling(ops_test: OpsTest) -> None:
8383
logger.info("Build charm locally")
8484

8585
sub_regex_failing_rejoin = (
86-
's/logger.debug("Recovering unit")'
86+
's/logger.info("Recovering unit")'
8787
'/self.charm._mysql.set_instance_offline_mode(True); raise RetryError("dummy")/'
8888
)
8989
src_patch(sub_regex=sub_regex_failing_rejoin, file_name="src/upgrade.py")

0 commit comments

Comments
 (0)