From b19aea77254eb34ebbd5f2a208722df0810be101 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Fri, 29 Dec 2023 12:28:24 -0500 Subject: [PATCH 1/7] new: `server_maintenance_mode` and `toggle_server_maintenance_mode` --- arango/cluster.py | 52 +++++++++++++++++++++++++++++++++++++++++++ docs/cluster.rst | 7 +++++- tests/test_cluster.py | 23 +++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/arango/cluster.py b/arango/cluster.py index a272f50c..54e43b0d 100644 --- a/arango/cluster.py +++ b/arango/cluster.py @@ -140,6 +140,58 @@ def response_handler(resp: Response) -> Json: return self._execute(request, response_handler) + def server_maintenance_mode(self, server_id: str) -> Result[Json]: + """Return the maintenance status for the given server. + + :param server_id: Server ID. + :type server_id: str + :return: Maintenance status for the given server. + :rtype: dict + :raise arango.exceptions.ClusterMaintenanceModeError: If retrieval fails. + """ + request = Request( + method="get", + endpoint=f"/_admin/cluster/maintenance/{server_id}", + ) + + def response_handler(resp: Response) -> Json: + if resp.is_success: + result: Json = resp.body.get("result", {}) + return result + + raise ClusterMaintenanceModeError(resp, request) + + return self._execute(request, response_handler) + + def toggle_server_maintenance_mode( + self, server_id: str, mode: str, timeout: Optional[int] = None + ) -> Result[Json]: + """Enable or disable the maintenance mode for the given server. + + :param server_id: Server ID. + :type server_id: str + :param mode: Maintenance mode. Allowed values are "normal" and "maintenance". + :type mode: str + :param timeout: Timeout in seconds. + :type timeout: Optional[int] + :return: Result of the operation. + :rtype: dict + :raise arango.exceptions.ClusterMaintenanceModeError: If toggle fails. + """ + request = Request( + method="put", + endpoint=f"/_admin/cluster/maintenance/{server_id}", + data={"mode": mode, "timeout": timeout}, + ) + + def response_handler(resp: Response) -> Json: + if resp.is_success: + return format_body(resp.body) + + raise ClusterMaintenanceModeError(resp, request) + + return self._execute(request, response_handler) + def health(self) -> Result[Json]: """Return the cluster health. diff --git a/docs/cluster.rst b/docs/cluster.rst index fbb3bb5e..fdb45bca 100644 --- a/docs/cluster.rst +++ b/docs/cluster.rst @@ -86,8 +86,13 @@ Below is an example on how to manage clusters using python-arango. cluster.server_engine(server_id) cluster.server_version(server_id) cluster.server_statistics(server_id) + cluster.server_maintenance_mode(server_id) - # Toggle maintenance mode (allowed values are "on" and "off"). + # Toggle Server maintenance mode (allowed values are "normal" and "maintenance"). + cluster.toggle_server_maintenance_mode(server_id, 'normal') + cluster.toggle_server_maintenance_mode(server_id, 'maintenance', timeout=30) + + # Toggle Cluster maintenance mode (allowed values are "on" and "off"). cluster.toggle_maintenance_mode('on') cluster.toggle_maintenance_mode('off') diff --git a/tests/test_cluster.py b/tests/test_cluster.py index bbc31778..e765c032 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -1,5 +1,6 @@ import warnings +import time import pytest from packaging import version @@ -99,6 +100,28 @@ def test_cluster_server_statistics(sys_db, bad_db, cluster): assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND} +def test_cluster_server_maintenance_mode(sys_db, bad_db, cluster): + if not cluster: + pytest.skip("Only tested in a cluster setup") + + server_id = sys_db.cluster.server_id() + result = sys_db.cluster.server_maintenance_mode(server_id) + assert result == {} + + with assert_raises(ClusterMaintenanceModeError) as err: + bad_db.cluster.server_maintenance_mode(server_id) + assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND} + + sys_db.cluster.toggle_server_maintenance_mode(server_id, "maintenance", timeout=1) + result = sys_db.cluster.server_maintenance_mode(server_id) + assert "Mode" in result + assert "Until" in result + + time.sleep(1) + result = sys_db.cluster.server_maintenance_mode(server_id) + assert result == {} + + def test_cluster_toggle_maintenance_mode(sys_db, bad_db, cluster): if not cluster: pytest.skip("Only tested in a cluster setup") From 56ab0f079f7a97cfe50e0ab51901cfabe1726243 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Fri, 29 Dec 2023 12:29:41 -0500 Subject: [PATCH 2/7] fix lint --- tests/test_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cluster.py b/tests/test_cluster.py index e765c032..da7212fa 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -1,6 +1,6 @@ +import time import warnings -import time import pytest from packaging import version From 24c4487d95ac4f25df6e0dac953508c4274c7146 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Fri, 29 Dec 2023 12:35:55 -0500 Subject: [PATCH 3/7] increase sleep --- tests/test_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cluster.py b/tests/test_cluster.py index da7212fa..361e5675 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -117,7 +117,7 @@ def test_cluster_server_maintenance_mode(sys_db, bad_db, cluster): assert "Mode" in result assert "Until" in result - time.sleep(1) + time.sleep(3) result = sys_db.cluster.server_maintenance_mode(server_id) assert result == {} From 8e71d8261cc15cd1fdbae7d5202ac72609c200e4 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Fri, 26 Jan 2024 13:14:07 -0500 Subject: [PATCH 4/7] increase sleep (again) --- tests/test_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cluster.py b/tests/test_cluster.py index 361e5675..a5531e9b 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -117,7 +117,7 @@ def test_cluster_server_maintenance_mode(sys_db, bad_db, cluster): assert "Mode" in result assert "Until" in result - time.sleep(3) + time.sleep(5) result = sys_db.cluster.server_maintenance_mode(server_id) assert result == {} From 261a89ec2502b1068e1b68b741f6889b16e8cc26 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Fri, 26 Jan 2024 13:15:01 -0500 Subject: [PATCH 5/7] revert 8e71d82 --- tests/test_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cluster.py b/tests/test_cluster.py index a5531e9b..361e5675 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -117,7 +117,7 @@ def test_cluster_server_maintenance_mode(sys_db, bad_db, cluster): assert "Mode" in result assert "Until" in result - time.sleep(5) + time.sleep(3) result = sys_db.cluster.server_maintenance_mode(server_id) assert result == {} From f71f9fb21c3010ad29f64ba07f6d65a1cfb1fa8d Mon Sep 17 00:00:00 2001 From: Alex Petenchea Date: Tue, 30 Jan 2024 17:56:11 +0200 Subject: [PATCH 6/7] finding a dbserver --- tests/test_cluster.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_cluster.py b/tests/test_cluster.py index f69b366a..b646be9e 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -117,7 +117,16 @@ def test_cluster_server_maintenance_mode(sys_db, bad_db, cluster): if not cluster: pytest.skip("Only tested in a cluster setup") - server_id = sys_db.cluster.server_id() + # Must be a DBServer + health = sys_db.cluster.health() + server_id = None + for server_id, info in health["Health"].items(): + if info["Role"] == "DBServer": + server_id = server_id + break + if server_id is None: + pytest.skip("No DBServer found in cluster") + result = sys_db.cluster.server_maintenance_mode(server_id) assert result == {} From d74d3c5ad1ca753ad9ee87f7106fddae336e94cd Mon Sep 17 00:00:00 2001 From: Alex Petenchea Date: Fri, 2 Feb 2024 15:28:38 +0200 Subject: [PATCH 7/7] Changing timeouts --- tests/test_cluster.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_cluster.py b/tests/test_cluster.py index b646be9e..39c2b8cf 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -134,12 +134,12 @@ def test_cluster_server_maintenance_mode(sys_db, bad_db, cluster): bad_db.cluster.server_maintenance_mode(server_id) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND} - sys_db.cluster.toggle_server_maintenance_mode(server_id, "maintenance", timeout=1) + sys_db.cluster.toggle_server_maintenance_mode(server_id, "maintenance", timeout=2) result = sys_db.cluster.server_maintenance_mode(server_id) assert "Mode" in result assert "Until" in result - time.sleep(3) + time.sleep(5) result = sys_db.cluster.server_maintenance_mode(server_id) assert result == {}