1use 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 service_control
57 .uninstall(¤t_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 let new_node_number = nodes_len + 1;
100 let new_service_name = format!("safenode{new_node_number}");
101
102 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 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 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(¤t_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}