sn_node_manager/
rpc.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
9use crate::{
10    add_services::config::InstallNodeServiceCtxBuilder, config::create_owned_dir, ServiceManager,
11    VerbosityLevel,
12};
13use color_eyre::{
14    eyre::{eyre, OptionExt},
15    Result,
16};
17use libp2p::PeerId;
18use sn_service_management::{
19    control::{ServiceControl, ServiceController},
20    rpc::RpcClient,
21    NodeRegistry, NodeService, NodeServiceData, ServiceStatus,
22};
23
24pub async fn restart_node_service(
25    node_registry: &mut NodeRegistry,
26    peer_id: PeerId,
27    retain_peer_id: bool,
28) -> Result<()> {
29    let nodes_len = node_registry.nodes.len();
30    let current_node_mut = node_registry
31        .nodes
32        .iter_mut()
33        .find(|node| node.peer_id.is_some_and(|id| id == peer_id))
34        .ok_or_eyre({
35            error!("Could not find the provided PeerId: {peer_id:?}");
36            format!("Could not find the provided PeerId: {peer_id:?}")
37        })?;
38    let current_node_clone = current_node_mut.clone();
39
40    let rpc_client = RpcClient::from_socket_addr(current_node_mut.rpc_socket_addr);
41    let service = NodeService::new(current_node_mut, Box::new(rpc_client));
42    let mut service_manager = ServiceManager::new(
43        service,
44        Box::new(ServiceController {}),
45        VerbosityLevel::Normal,
46    );
47    service_manager.stop().await?;
48
49    let service_control = ServiceController {};
50    if retain_peer_id {
51        debug!(
52            "Retaining the peer id: {peer_id:?} for the node: {:?}",
53            current_node_clone.service_name
54        );
55        // reuse the same port and root dir to retain peer id.
56        service_control
57            .uninstall(&current_node_clone.service_name, false)
58            .map_err(|err| {
59                eyre!(
60                    "Error while uninstalling node {:?} with: {err:?}",
61                    current_node_clone.service_name
62                )
63            })?;
64        let install_ctx = InstallNodeServiceCtxBuilder {
65            autostart: current_node_clone.auto_restart,
66            bootstrap_peers: node_registry.bootstrap_peers.clone(),
67            data_dir_path: current_node_clone.data_dir_path.clone(),
68            env_variables: node_registry.environment_variables.clone(),
69            evm_network: current_node_clone.evm_network.clone(),
70            genesis: current_node_clone.genesis,
71            home_network: current_node_clone.home_network,
72            local: current_node_clone.local,
73            log_dir_path: current_node_clone.log_dir_path.clone(),
74            log_format: current_node_clone.log_format,
75            max_archived_log_files: current_node_clone.max_archived_log_files,
76            max_log_files: current_node_clone.max_log_files,
77            metrics_port: None,
78            owner: current_node_clone.owner.clone(),
79            name: current_node_clone.service_name.clone(),
80            node_ip: current_node_clone.node_ip,
81            node_port: current_node_clone.get_safenode_port(),
82            rewards_address: current_node_clone.rewards_address,
83            rpc_socket_addr: current_node_clone.rpc_socket_addr,
84            safenode_path: current_node_clone.safenode_path.clone(),
85            service_user: current_node_clone.user.clone(),
86            upnp: current_node_clone.upnp,
87        }
88        .build()?;
89        service_control.install(install_ctx, false).map_err(|err| {
90            eyre!(
91                "Error while installing node {:?} with: {err:?}",
92                current_node_clone.service_name
93            )
94        })?;
95        service_manager.start().await?;
96    } else {
97        debug!("Starting a new node since retain peer id is false.");
98        // else start a new node instance.
99        let new_node_number = nodes_len + 1;
100        let new_service_name = format!("safenode{new_node_number}");
101
102        // modify the paths & copy safenode binary
103        // example path "log_dir_path":"/var/log/safenode/safenode18"
104        let log_dir_path = {
105            let mut log_dir_path = current_node_clone.log_dir_path.clone();
106            log_dir_path.pop();
107            log_dir_path.join(&new_service_name)
108        };
109        // example path "data_dir_path":"/var/safenode-manager/services/safenode18"
110        let data_dir_path = {
111            let mut data_dir_path = current_node_clone.data_dir_path.clone();
112            data_dir_path.pop();
113            data_dir_path.join(&new_service_name)
114        };
115
116        create_owned_dir(
117            log_dir_path.clone(),
118            current_node_clone.user.as_ref().ok_or_else(|| {
119                error!("The user must be set in the RPC context");
120                eyre!("The user must be set in the RPC context")
121            })?,
122        )
123        .map_err(|err| {
124            error!(
125                "Error while creating owned dir for {:?}: {err:?}",
126                current_node_clone.user
127            );
128            eyre!(
129                "Error while creating owned dir for {:?}: {err:?}",
130                current_node_clone.user
131            )
132        })?;
133        debug!("Created data dir: {data_dir_path:?} for the new node");
134        create_owned_dir(
135            data_dir_path.clone(),
136            current_node_clone
137                .user
138                .as_ref()
139                .ok_or_else(|| eyre!("The user must be set in the RPC context"))?,
140        )
141        .map_err(|err| {
142            eyre!(
143                "Error while creating owned dir for {:?}: {err:?}",
144                current_node_clone.user
145            )
146        })?;
147        // example path "safenode_path":"/var/safenode-manager/services/safenode18/safenode"
148        let safenode_path = {
149            debug!("Copying safenode binary");
150            let mut safenode_path = current_node_clone.safenode_path.clone();
151            let safenode_file_name = safenode_path
152                .file_name()
153                .ok_or_eyre("Could not get filename from the current node's safenode path")?
154                .to_string_lossy()
155                .to_string();
156            safenode_path.pop();
157            safenode_path.pop();
158
159            let safenode_path = safenode_path.join(&new_service_name);
160            create_owned_dir(
161                data_dir_path.clone(),
162                current_node_clone
163                    .user
164                    .as_ref()
165                    .ok_or_else(|| eyre!("The user must be set in the RPC context"))?,
166            )
167            .map_err(|err| {
168                eyre!(
169                    "Error while creating owned dir for {:?}: {err:?}",
170                    current_node_clone.user
171                )
172            })?;
173            let safenode_path = safenode_path.join(safenode_file_name);
174
175            std::fs::copy(&current_node_clone.safenode_path, &safenode_path).map_err(|err| {
176                eyre!(
177                    "Failed to copy safenode bin from {:?} to {safenode_path:?} with err: {err}",
178                    current_node_clone.safenode_path
179                )
180            })?;
181            safenode_path
182        };
183
184        let install_ctx = InstallNodeServiceCtxBuilder {
185            autostart: current_node_clone.auto_restart,
186            bootstrap_peers: node_registry.bootstrap_peers.clone(),
187            data_dir_path: data_dir_path.clone(),
188            env_variables: node_registry.environment_variables.clone(),
189            evm_network: current_node_clone.evm_network.clone(),
190            genesis: current_node_clone.genesis,
191            home_network: current_node_clone.home_network,
192            local: current_node_clone.local,
193            log_dir_path: log_dir_path.clone(),
194            log_format: current_node_clone.log_format,
195            name: new_service_name.clone(),
196            max_archived_log_files: current_node_clone.max_archived_log_files,
197            max_log_files: current_node_clone.max_log_files,
198            metrics_port: None,
199            node_ip: current_node_clone.node_ip,
200            node_port: None,
201            owner: None,
202            rewards_address: current_node_clone.rewards_address,
203            rpc_socket_addr: current_node_clone.rpc_socket_addr,
204            safenode_path: safenode_path.clone(),
205            service_user: current_node_clone.user.clone(),
206            upnp: current_node_clone.upnp,
207        }
208        .build()?;
209        service_control.install(install_ctx, false).map_err(|err| {
210            eyre!("Error while installing node {new_service_name:?} with: {err:?}",)
211        })?;
212
213        let mut node = NodeServiceData {
214            auto_restart: current_node_clone.auto_restart,
215            connected_peers: None,
216            data_dir_path,
217            evm_network: current_node_clone.evm_network,
218            genesis: current_node_clone.genesis,
219            home_network: current_node_clone.home_network,
220            listen_addr: None,
221            local: current_node_clone.local,
222            log_dir_path,
223            log_format: current_node_clone.log_format,
224            max_archived_log_files: current_node_clone.max_archived_log_files,
225            max_log_files: current_node_clone.max_log_files,
226            metrics_port: None,
227            node_ip: current_node_clone.node_ip,
228            node_port: None,
229            number: new_node_number as u16,
230            owner: None,
231            peer_id: None,
232            pid: None,
233            rewards_address: current_node_clone.rewards_address,
234            reward_balance: current_node_clone.reward_balance,
235            rpc_socket_addr: current_node_clone.rpc_socket_addr,
236            safenode_path,
237            service_name: new_service_name.clone(),
238            status: ServiceStatus::Added,
239            upnp: current_node_clone.upnp,
240            user: current_node_clone.user.clone(),
241            user_mode: false,
242            version: current_node_clone.version.clone(),
243        };
244
245        let rpc_client = RpcClient::from_socket_addr(node.rpc_socket_addr);
246        let service = NodeService::new(&mut node, Box::new(rpc_client));
247        let mut service_manager = ServiceManager::new(
248            service,
249            Box::new(ServiceController {}),
250            VerbosityLevel::Normal,
251        );
252        service_manager.start().await?;
253        node_registry
254            .nodes
255            .push(service_manager.service.service_data.clone());
256    };
257
258    Ok(())
259}