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