diff --git a/coretex/cli/commands/node.py b/coretex/cli/commands/node.py index 2e76f050..221de5a1 100644 --- a/coretex/cli/commands/node.py +++ b/coretex/cli/commands/node.py @@ -32,6 +32,8 @@ @click.option("--image", type = str, help = "Docker image url") @onBeforeCommandExecute(node_module.initializeNodeConfiguration) def start(image: Optional[str]) -> None: + config = loadConfig() + if node_module.isRunning(): if not clickPrompt( "Node is already running. Do you wish to restart the Node? (Y/n)", @@ -41,13 +43,11 @@ def start(image: Optional[str]) -> None: ): return - node_module.stop() + node_module.stop(config.get("nodeId", node_module.fetchNodeId(config["nodeName"]))) if node_module.exists(): node_module.clean() - config = loadConfig() - if image is not None: config["image"] = image # store forced image (flagged) so we can run autoupdate afterwards saveConfig(config) @@ -65,11 +65,13 @@ def start(image: Optional[str]) -> None: @click.command() def stop() -> None: + config = loadConfig() + if not node_module.isRunning(): errorEcho("Node is already offline.") return - node_module.stop() + node_module.stop(config.get("nodeId", node_module.fetchNodeId(config["nodeName"]))) @click.command() @@ -106,7 +108,7 @@ def update(autoAccept: bool, autoDecline: bool) -> None: ): return - node_module.stop() + node_module.stop(config.get("nodeId", node_module.fetchNodeId(config["nodeName"]))) if not node_module.shouldUpdate(dockerImage): successEcho("Node is already up to date.") @@ -127,7 +129,7 @@ def update(autoAccept: bool, autoDecline: bool) -> None: ): return - node_module.stop() + node_module.stop(config.get("nodeId", node_module.fetchNodeId(config["nodeName"]))) stdEcho("Updating node...") node_module.start(dockerImage, config) @@ -139,6 +141,8 @@ def update(autoAccept: bool, autoDecline: bool) -> None: @click.command() @click.option("--verbose", is_flag = True, help = "Configure node settings manually.") def config(verbose: bool) -> None: + config = loadConfig() + if node_module.isRunning(): if not clickPrompt( "Node is already running. Do you wish to stop the Node? (Y/n)", @@ -149,9 +153,7 @@ def config(verbose: bool) -> None: errorEcho("If you wish to reconfigure your node, use coretex node stop commands first.") return - node_module.stop() - - config = loadConfig() + node_module.stop(config.get("nodeId", node_module.fetchNodeId(config["nodeName"]))) if isNodeConfigured(config): if not clickPrompt( diff --git a/coretex/cli/modules/node.py b/coretex/cli/modules/node.py index 52b4ce4f..79961506 100644 --- a/coretex/cli/modules/node.py +++ b/coretex/cli/modules/node.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Tuple, List from enum import Enum from pathlib import Path from base64 import b64encode @@ -117,10 +117,53 @@ def clean() -> None: raise NodeException("Failed to clean inactive Coretex Node.") -def stop() -> None: +def fetchNodeId(name: str) -> int: + config = loadConfig() + params = { + "machine_name": f"={name}" + } + + response = networkManager.get("service", params) + if response.hasFailed(): + raise NetworkRequestError(response, "Failed to fetch node id.") + + responseJson = response.getJson(dict) + data = responseJson.get("data") + + if not isinstance(data, list): + raise TypeError(f"Invalid \"data\" type {type(data)}. Expected: \"list\"") + + if len(data) == 0: + raise ValueError(f"Node with name \"{name}\" not found.") + + nodeJson = data[0] + if not isinstance(nodeJson, dict): + raise TypeError(f"Invalid \"nodeJson\" type {type(nodeJson)}. Expected: \"dict\"") + + nodeId = nodeJson.get("id") + if not isinstance(nodeId, int): + raise TypeError(f"Invalid \"nodeId\" type {type(nodeId)}. Expected: \"int\"") + + config["nodeId"] = nodeId + saveConfig(config) + return nodeId + + +def deactivateNode(id: Optional[int]) -> None: + params = { + "id": id + } + + response = networkManager.post("service/deactivate", params) + if response.hasFailed(): + raise NetworkRequestError(response, "Failed to deactivate node.") + + +def stop(nodeId: int) -> None: try: progressEcho("Stopping Coretex Node...") docker.stopContainer(config_defaults.DOCKER_CONTAINER_NAME) + deactivateNode(nodeId) clean() successEcho("Successfully stopped Coretex Node....") except BaseException as ex: @@ -178,7 +221,7 @@ def registerNode( publicKey: Optional[bytes] = None, nearWalletId: Optional[str] = None, endpointInvocationPrice: Optional[float] = None -) -> str: +) -> Tuple[int, str]: params: Dict[str, Any] = { "machine_name": name, @@ -200,11 +243,12 @@ def registerNode( raise NetworkRequestError(response, "Failed to configure node. Please try again...") accessToken = response.getJson(dict).get("access_token") + nodeId = response.getJson(dict).get("id") - if not isinstance(accessToken, str): + if not isinstance(accessToken, str) or not isinstance(nodeId, int): raise TypeError("Something went wrong. Please try again...") - return accessToken + return nodeId, accessToken def selectImageType() -> ImageType: @@ -348,7 +392,7 @@ def isConfigurationValid(config: Dict[str, Any]) -> bool: isValid = False if config["nodeSwap"] > swapLimit: - errorEcho(f"Configuration not valid. RAM limit in Docker Desktop ({swapLimit}GB) is lower than the configured value ({config['nodeSwap']}GB)") + errorEcho(f"Configuration not valid. SWAP memory limit in Docker Desktop ({swapLimit}GB) is lower than the configured value ({config['nodeSwap']}GB)") isValid = False if config["nodeRam"] < config_defaults.MINIMUM_RAM: @@ -383,7 +427,7 @@ def configureNode(config: Dict[str, Any], verbose: bool) -> None: config["storagePath"] = config_defaults.DEFAULT_STORAGE_PATH config["nodeRam"] = int(min(max(config_defaults.MINIMUM_RAM, ramLimit), config_defaults.DEFAULT_RAM)) - config["nodeSwap"] = config_defaults.DEFAULT_SWAP_MEMORY + config["nodeSwap"] = int(min(config_defaults.DEFAULT_SWAP_MEMORY, swapLimit)) config["nodeSharedMemory"] = config_defaults.DEFAULT_SHARED_MEMORY config["cpuCount"] = int(min(cpuLimit, config_defaults.DEFAULT_CPU_COUNT)) config["nodeMode"] = config_defaults.DEFAULT_NODE_MODE @@ -434,7 +478,9 @@ def configureNode(config: Dict[str, Any], verbose: bool) -> None: else: stdEcho("To configure node manually run coretex node config with --verbose flag.") - config["nodeAccessToken"] = registerNode(config["nodeName"], nodeMode, publicKey, nearWalletId, endpointInvocationPrice) + nodeId, nodeAccessToken = registerNode(config["nodeName"], nodeMode, publicKey, nearWalletId, endpointInvocationPrice) + config["nodeId"] = nodeId + config["nodeAccessToken"] = nodeAccessToken config["nodeMode"] = nodeMode @@ -458,7 +504,7 @@ def initializeNodeConfiguration() -> None: errorEcho("If you wish to reconfigure your node, use \"coretex node stop\" command first.") return - stop() + stop(config["nodeId"]) configureNode(config, verbose = False) saveConfig(config)