sn_node_manager/cmd/
faucet.rs1use super::{download_and_get_upgrade_bin_path, print_upgrade_summary};
10use crate::{
11 add_services::{add_faucet, config::AddFaucetServiceOptions},
12 config::{self, is_running_as_root},
13 helpers::{download_and_extract_release, get_bin_version},
14 print_banner, ServiceManager, VerbosityLevel,
15};
16use color_eyre::{eyre::eyre, Result};
17use colored::Colorize;
18use semver::Version;
19use sn_peers_acquisition::PeersArgs;
20use sn_releases::{ReleaseType, SafeReleaseRepoActions};
21use sn_service_management::{
22 control::{ServiceControl, ServiceController},
23 FaucetService, NodeRegistry, UpgradeOptions,
24};
25use sn_transfers::get_faucet_data_dir;
26use std::path::PathBuf;
27
28pub async fn add(
29 env_variables: Option<Vec<(String, String)>>,
30 log_dir_path: Option<PathBuf>,
31 peers_args: PeersArgs,
32 src_path: Option<PathBuf>,
33 url: Option<String>,
34 version: Option<String>,
35 verbosity: VerbosityLevel,
36) -> Result<()> {
37 if !is_running_as_root() {
38 error!("The faucet add command must run as the root user");
39 return Err(eyre!("The add command must run as the root user"));
40 }
41
42 if verbosity != VerbosityLevel::Minimal {
43 print_banner("Add Faucet Service");
44 }
45
46 let service_user = "safe";
47 let service_manager = ServiceController {};
48 service_manager.create_service_user(service_user)?;
49
50 let service_log_dir_path = config::get_service_log_dir_path(
51 ReleaseType::Faucet,
52 log_dir_path,
53 Some(service_user.to_string()),
54 )?;
55
56 let mut node_registry = NodeRegistry::load(&config::get_node_registry_path()?)?;
57 let release_repo = <dyn SafeReleaseRepoActions>::default_config();
58
59 let (faucet_src_bin_path, version) = if let Some(path) = src_path {
60 let version = get_bin_version(&path)?;
61 (path, version)
62 } else {
63 download_and_extract_release(
64 ReleaseType::Faucet,
65 url.clone(),
66 version,
67 &*release_repo,
68 verbosity,
69 None,
70 )
71 .await?
72 };
73
74 info!("Adding faucet service");
75 add_faucet(
76 AddFaucetServiceOptions {
77 bootstrap_peers: peers_args.get_peers().await?,
78 env_variables,
79 faucet_src_bin_path,
80 faucet_install_bin_path: PathBuf::from("/usr/local/bin/faucet"),
81 local: false,
82 service_data_dir_path: get_faucet_data_dir(),
83 service_log_dir_path,
84 user: service_user.to_string(),
85 version,
86 },
87 &mut node_registry,
88 &service_manager,
89 verbosity,
90 )?;
91
92 Ok(())
93}
94
95pub async fn start(verbosity: VerbosityLevel) -> Result<()> {
96 if !is_running_as_root() {
97 error!("The faucet start command must run as the root user");
98 return Err(eyre!("The start command must run as the root user"));
99 }
100
101 let mut node_registry = NodeRegistry::load(&config::get_node_registry_path()?)?;
102 if let Some(faucet) = &mut node_registry.faucet {
103 if verbosity != VerbosityLevel::Minimal {
104 print_banner("Start Faucet Service");
105 }
106 info!("Starting faucet service");
107
108 let service = FaucetService::new(faucet, Box::new(ServiceController {}));
109 let mut service_manager = ServiceManager::new(
110 service,
111 Box::new(ServiceController {}),
112 VerbosityLevel::Normal,
113 );
114 service_manager.start().await?;
115
116 node_registry.save()?;
117 return Ok(());
118 }
119
120 error!("The faucet service has not been added yet");
121 Err(eyre!("The faucet service has not been added yet"))
122}
123
124pub async fn stop(verbosity: VerbosityLevel) -> Result<()> {
125 if !is_running_as_root() {
126 error!("The faucet stop command must run as the root user");
127 return Err(eyre!("The stop command must run as the root user"));
128 }
129
130 let mut node_registry = NodeRegistry::load(&config::get_node_registry_path()?)?;
131 if let Some(faucet) = &mut node_registry.faucet {
132 if verbosity != VerbosityLevel::Minimal {
133 print_banner("Stop Faucet Service");
134 }
135 info!("Stopping faucet service");
136
137 let service = FaucetService::new(faucet, Box::new(ServiceController {}));
138 let mut service_manager =
139 ServiceManager::new(service, Box::new(ServiceController {}), verbosity);
140 service_manager.stop().await?;
141
142 node_registry.save()?;
143
144 return Ok(());
145 }
146
147 error!("The faucet service has not been added yet");
148 Err(eyre!("The faucet service has not been added yet"))
149}
150
151pub async fn upgrade(
152 do_not_start: bool,
153 force: bool,
154 provided_env_variables: Option<Vec<(String, String)>>,
155 url: Option<String>,
156 version: Option<String>,
157 verbosity: VerbosityLevel,
158) -> Result<()> {
159 if !is_running_as_root() {
160 return Err(eyre!("The upgrade command must run as the root user"));
161 }
162
163 let mut node_registry = NodeRegistry::load(&config::get_node_registry_path()?)?;
164 if node_registry.faucet.is_none() {
165 println!("No faucet service has been created yet. No upgrade required.");
166 return Ok(());
167 }
168
169 if verbosity != VerbosityLevel::Minimal {
170 print_banner("Upgrade Faucet Service");
171 }
172 info!("Upgrading faucet service");
173
174 let (upgrade_bin_path, target_version) =
175 download_and_get_upgrade_bin_path(None, ReleaseType::Faucet, url, version, verbosity)
176 .await?;
177 let faucet = node_registry.faucet.as_mut().unwrap();
178
179 if !force {
180 let current_version = Version::parse(&faucet.version)?;
181 if target_version <= current_version {
182 println!(
183 "{} The faucet is already at the latest version",
184 "✓".green()
185 );
186 return Ok(());
187 }
188 }
189
190 let env_variables = if provided_env_variables.is_some() {
191 &provided_env_variables
192 } else {
193 &node_registry.environment_variables
194 };
195 let options = UpgradeOptions {
196 auto_restart: true,
197 bootstrap_peers: node_registry.bootstrap_peers.clone(),
198 env_variables: env_variables.clone(),
199 force,
200 start_service: !do_not_start,
201 target_bin_path: upgrade_bin_path.clone(),
202 target_version: target_version.clone(),
203 };
204 let service = FaucetService::new(faucet, Box::new(ServiceController {}));
205 let mut service_manager =
206 ServiceManager::new(service, Box::new(ServiceController {}), verbosity);
207
208 match service_manager.upgrade(options).await {
209 Ok(upgrade_result) => {
210 print_upgrade_summary(vec![("faucet".to_string(), upgrade_result)]);
211 node_registry.save()?;
212 Ok(())
213 }
214 Err(e) => Err(eyre!("Upgrade failed: {e}")),
215 }
216}