ant_node_manager/cmd/
local.rs

1// Copyright (C) 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9#![allow(clippy::too_many_arguments)]
10
11use super::get_bin_path;
12use crate::{
13    add_services::config::PortRange,
14    local::{kill_network, run_network, LocalNetworkOptions},
15    print_banner, status_report, VerbosityLevel,
16};
17use ant_bootstrap::InitialPeersConfig;
18use ant_evm::{EvmNetwork, RewardsAddress};
19use ant_logging::LogFormat;
20use ant_releases::{AntReleaseRepoActions, ReleaseType};
21use ant_service_management::{
22    control::ServiceController, get_local_node_registry_path, NodeRegistry,
23};
24use color_eyre::{eyre::eyre, Help, Report, Result};
25use std::path::PathBuf;
26
27pub async fn join(
28    build: bool,
29    count: u16,
30    enable_metrics_server: bool,
31    interval: u64,
32    metrics_port: Option<PortRange>,
33    node_path: Option<PathBuf>,
34    node_port: Option<PortRange>,
35    node_version: Option<String>,
36    log_format: Option<LogFormat>,
37    _peers_args: InitialPeersConfig,
38    rpc_port: Option<PortRange>,
39    rewards_address: RewardsAddress,
40    evm_network: Option<EvmNetwork>,
41    skip_validation: bool,
42    verbosity: VerbosityLevel,
43) -> Result<(), Report> {
44    if verbosity != VerbosityLevel::Minimal {
45        print_banner("Joining Local Network");
46    }
47    info!("Joining local network");
48
49    if (enable_metrics_server || metrics_port.is_some()) && !cfg!(feature = "open-metrics") && build
50    {
51        return Err(eyre!(
52        "Metrics server is not available. Please enable the open-metrics feature flag. Run the command with the --features open-metrics"
53    ));
54    }
55
56    let local_node_reg_path = &get_local_node_registry_path()?;
57    let mut local_node_registry = NodeRegistry::load(local_node_reg_path)?;
58
59    let release_repo = <dyn AntReleaseRepoActions>::default_config();
60
61    let antnode_bin_path = get_bin_path(
62        build,
63        node_path,
64        ReleaseType::AntNode,
65        node_version,
66        &*release_repo,
67        verbosity,
68    )
69    .await?;
70
71    let options = LocalNetworkOptions {
72        antnode_bin_path,
73        enable_metrics_server,
74        interval,
75        join: true,
76        metrics_port,
77        node_count: count,
78        node_port,
79        peers: None,
80        rpc_port,
81        skip_validation,
82        log_format,
83        rewards_address,
84        evm_network,
85    };
86    run_network(options, &mut local_node_registry, &ServiceController {}).await?;
87    Ok(())
88}
89
90pub fn kill(keep_directories: bool, verbosity: VerbosityLevel) -> Result<()> {
91    let local_reg_path = &get_local_node_registry_path()?;
92    let local_node_registry = NodeRegistry::load(local_reg_path)?;
93    if local_node_registry.nodes.is_empty() {
94        info!("No local network is currently running, cannot kill it");
95        println!("No local network is currently running");
96    } else {
97        if verbosity != VerbosityLevel::Minimal {
98            print_banner("Killing Local Network");
99        }
100        info!("Kill local network");
101        kill_network(&local_node_registry, keep_directories)?;
102        std::fs::remove_file(local_reg_path)?;
103    }
104    Ok(())
105}
106
107pub async fn run(
108    build: bool,
109    clean: bool,
110    count: u16,
111    enable_metrics_server: bool,
112    interval: u64,
113    metrics_port: Option<PortRange>,
114    node_path: Option<PathBuf>,
115    node_port: Option<PortRange>,
116    node_version: Option<String>,
117    log_format: Option<LogFormat>,
118    rpc_port: Option<PortRange>,
119    rewards_address: RewardsAddress,
120    evm_network: Option<EvmNetwork>,
121    skip_validation: bool,
122    verbosity: VerbosityLevel,
123) -> Result<(), Report> {
124    if (enable_metrics_server || metrics_port.is_some()) && !cfg!(feature = "open-metrics") && build
125    {
126        return Err(eyre!(
127        "Metrics server is not available. Please enable the open-metrics feature flag. Run the command with the --features open-metrics"
128    ));
129    }
130
131    // In the clean case, the node registry must be loaded *after* the existing network has
132    // been killed, which clears it out.
133    let local_node_reg_path = &get_local_node_registry_path()?;
134    let mut local_node_registry: NodeRegistry = if clean {
135        debug!(
136            "Clean set to true, removing client, node dir, local registry and killing the network."
137        );
138        let client_data_path = dirs_next::data_dir()
139            .ok_or_else(|| eyre!("Could not obtain user's data directory"))?
140            .join("autonomi")
141            .join("client");
142        if client_data_path.is_dir() {
143            std::fs::remove_dir_all(client_data_path)?;
144        }
145        if local_node_reg_path.exists() {
146            std::fs::remove_file(local_node_reg_path)?;
147        }
148        kill(false, verbosity)?;
149        NodeRegistry::load(local_node_reg_path)?
150    } else {
151        let local_node_registry = NodeRegistry::load(local_node_reg_path)?;
152        if !local_node_registry.nodes.is_empty() {
153            error!("A local network is already running, cannot run a new one");
154            return Err(eyre!("A local network is already running")
155                .suggestion("Use the kill command to destroy the network then try again"));
156        }
157        local_node_registry
158    };
159
160    if verbosity != VerbosityLevel::Minimal {
161        print_banner("Launching Local Network");
162    }
163    info!("Launching local network");
164
165    let release_repo = <dyn AntReleaseRepoActions>::default_config();
166
167    let antnode_bin_path = get_bin_path(
168        build,
169        node_path,
170        ReleaseType::AntNode,
171        node_version,
172        &*release_repo,
173        verbosity,
174    )
175    .await?;
176
177    let options = LocalNetworkOptions {
178        antnode_bin_path,
179        enable_metrics_server,
180        join: false,
181        interval,
182        metrics_port,
183        node_port,
184        node_count: count,
185        peers: None,
186        rpc_port,
187        skip_validation,
188        log_format,
189        rewards_address,
190        evm_network,
191    };
192    run_network(options, &mut local_node_registry, &ServiceController {}).await?;
193
194    local_node_registry.save()?;
195    Ok(())
196}
197
198pub async fn status(details: bool, fail: bool, json: bool) -> Result<()> {
199    let mut local_node_registry = NodeRegistry::load(&get_local_node_registry_path()?)?;
200    if !json {
201        print_banner("Local Network");
202    }
203    status_report(
204        &mut local_node_registry,
205        &ServiceController {},
206        details,
207        json,
208        fail,
209        true,
210    )
211    .await?;
212    local_node_registry.save()?;
213    Ok(())
214}