sn_node_manager/cmd/
auditor.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 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}