From a7600ea8d43d2bd6f7a0511a9b763d0e9ee6ca70 Mon Sep 17 00:00:00 2001 From: Karl Bartel Date: Tue, 5 May 2020 15:37:59 +0200 Subject: [PATCH] Provide API endpoint to shutdown Raiden This can then be used in the WebUI. Closes https://github.com/raiden-network/raiden/issues/6113. --- raiden/api/python.py | 3 +++ raiden/api/rest.py | 8 ++++++++ raiden/api/v1/resources.py | 6 ++++++ raiden/tests/integration/api/rest/test_rest.py | 16 ++++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/raiden/api/python.py b/raiden/api/python.py index d6a7cc79d9..9d527ad96b 100644 --- a/raiden/api/python.py +++ b/raiden/api/python.py @@ -1332,3 +1332,6 @@ def get_pending_transfers( channel_id = partner_channel.identifier return transfer_tasks_view(transfer_tasks, token_address, channel_id) + + def shutdown(self) -> None: + self.raiden.stop() diff --git a/raiden/api/rest.py b/raiden/api/rest.py index 21941fd3c9..e8b1da6144 100644 --- a/raiden/api/rest.py +++ b/raiden/api/rest.py @@ -54,6 +54,7 @@ PendingTransfersResourceByTokenAndPartnerAddress, RaidenInternalEventsResource, RegisterTokenResource, + ShutdownResource, StatusResource, TokensResource, VersionResource, @@ -104,6 +105,7 @@ from raiden.transfer.state import ChannelState, NettingChannelState from raiden.ui.sync import blocks_to_sync from raiden.utils.formatting import optional_address_to_string, to_checksum_address +from raiden.utils.gevent import spawn_named from raiden.utils.http import split_endpoint from raiden.utils.runnable import Runnable from raiden.utils.system import get_system_spec @@ -166,6 +168,7 @@ "pending_transfers_resource_by_token_and_partner", ), ("/status", StatusResource), + ("/shutdown", ShutdownResource), ("/_debug/blockchain_events/network", BlockchainEventsNetworkResource), ("/_debug/blockchain_events/tokens/", BlockchainEventsTokenResource), ( @@ -1432,3 +1435,8 @@ def get_status(self) -> Response: return api_response(result=dict(status="syncing", blocks_to_sync=to_sync)) else: return api_response(result=dict(status="unavailable")) + + def shutdown(self) -> Response: + shutdown_greenlet = spawn_named("trigger shutdown", self.raiden_api.shutdown) + shutdown_greenlet.link_exception(self.raiden_api.raiden.on_error) + return api_response(result=dict(status="shutdown")) diff --git a/raiden/api/v1/resources.py b/raiden/api/v1/resources.py index 869c6c6e7a..01638847f3 100644 --- a/raiden/api/v1/resources.py +++ b/raiden/api/v1/resources.py @@ -322,3 +322,9 @@ def get(self, token_address: TokenAddress, partner_address: Address) -> Response class StatusResource(BaseResource): def get(self) -> Response: return self.rest_api.get_status() + + +class ShutdownResource(BaseResource): + @if_api_available + def post(self) -> Response: + return self.rest_api.shutdown() diff --git a/raiden/tests/integration/api/rest/test_rest.py b/raiden/tests/integration/api/rest/test_rest.py index 7be504c3a5..68660be946 100644 --- a/raiden/tests/integration/api/rest/test_rest.py +++ b/raiden/tests/integration/api/rest/test_rest.py @@ -1244,3 +1244,19 @@ def test_api_testnet_token_mint(api_server_test_instance: APIServer, token_addre request = grequests.post(url, json=dict(to=user_address[:-2], value=10)) response = request.send().response assert_response_with_error(response, HTTPStatus.BAD_REQUEST) + + +@raise_on_failure +@pytest.mark.parametrize("number_of_nodes", [1]) +@pytest.mark.parametrize("channels_per_node", [0]) +@pytest.mark.parametrize("enable_rest_api", [True]) +def test_shutdown(api_server_test_instance: APIServer): + """ Node must stop after shutdown is called """ + url = ("http://localhost:{port}/api/v1/shutdown").format( + port=api_server_test_instance.config.port + ) + response = grequests.post(url).send().response + + assert_response_with_code(response, HTTPStatus.OK) + finished = gevent.joinall({api_server_test_instance}, timeout=10, raise_error=True) + assert finished, "The Raiden node did not shut down!"