Skip to main content

edera_check/checkers/postinstall/
services.rs

1use async_trait::async_trait;
2use futures::{FutureExt, future::join_all};
3use log::debug;
4
5use crate::helpers::{
6    CheckGroup, CheckGroupCategory, CheckGroupResult, CheckResult,
7    CheckResultValue::{Errored, Failed, Passed},
8    host_executor::HostNamespaceExecutor,
9    services as svchelpers,
10};
11
12const GROUP_IDENTIFIER: &str = "services";
13const NAME: &str = "Service Status Checks";
14
15pub struct ServiceChecks {
16    host_executor: HostNamespaceExecutor,
17}
18
19impl ServiceChecks {
20    pub fn new(host_executor: HostNamespaceExecutor) -> Self {
21        ServiceChecks { host_executor }
22    }
23
24    /// Run all the recorders asynchronously, then
25    /// join and collect the results.
26    pub async fn run_all(&self) -> CheckGroupResult {
27        let results = join_all([
28            self.check_daemon().boxed(),
29            self.check_storage().boxed(),
30            self.check_network().boxed(),
31        ])
32        .await;
33
34        let mut group_result = Passed;
35        for res in results.iter() {
36            // Set group result to Failed if we failed and aren't already in an Errored state
37            if !matches!(group_result, Errored(_)) && matches!(res.result, Failed(_)) {
38                group_result = Failed(String::from("group failed"));
39            }
40
41            if matches!(res.result, Errored(_)) {
42                group_result = Errored(String::from("group errored"));
43            }
44        }
45
46        CheckGroupResult {
47            name: NAME.to_string(),
48            result: group_result,
49            results,
50        }
51    }
52
53    /// Checks that the `protect-daemon` service is active.
54    ///
55    /// Manual equivalent:
56    /// ```sh
57    /// systemctl is-active protect-daemon
58    /// # or on OpenRC: rc-service protect-daemon status
59    /// ```
60    pub async fn check_daemon(&self) -> CheckResult {
61        let name = "Protect daemon status";
62        let sname = "protect-daemon";
63        let init = svchelpers::detect_init_system(&self.host_executor).await;
64        debug!("detected init system: {:?}\n", init);
65
66        match svchelpers::is_running(&self.host_executor, sname.into(), init).await {
67            Ok(true) => CheckResult::new(name, Passed),
68            Ok(false) => CheckResult::new(name, Failed(format!("{} not running", &sname))),
69            Err(e) => CheckResult::new(
70                name,
71                Errored(format!("failed to check service {sname}: {e}")),
72            ),
73        }
74    }
75
76    /// Checks that the `protect-storage` service is active.
77    ///
78    /// Manual equivalent:
79    /// ```sh
80    /// systemctl is-active protect-storage
81    /// # or on OpenRC: rc-service protect-storage status
82    /// ```
83    pub async fn check_storage(&self) -> CheckResult {
84        let name = "Protect storage daemon status";
85        let sname = "protect-storage";
86        let init = svchelpers::detect_init_system(&self.host_executor).await;
87        debug!("detected init system: {:?}\n", init);
88
89        match svchelpers::is_running(&self.host_executor, sname.into(), init).await {
90            Ok(true) => CheckResult::new(name, Passed),
91            Ok(false) => CheckResult::new(name, Failed(format!("{} not running", &sname))),
92            Err(e) => CheckResult::new(
93                name,
94                Errored(format!("failed to check service {sname}: {e}")),
95            ),
96        }
97    }
98
99    /// Checks that the `protect-network` service is active.
100    ///
101    /// Manual equivalent:
102    /// ```sh
103    /// systemctl is-active protect-network
104    /// # or on OpenRC: rc-service protect-network status
105    /// ```
106    pub async fn check_network(&self) -> CheckResult {
107        let name = "Protect network daemon status";
108        let sname = "protect-network";
109        let init = svchelpers::detect_init_system(&self.host_executor).await;
110        debug!("detected init system: {:?}\n", init);
111
112        match svchelpers::is_running(&self.host_executor, sname.into(), init).await {
113            Ok(true) => CheckResult::new(name, Passed),
114            Ok(false) => CheckResult::new(name, Failed(format!("{} not running", &sname))),
115            Err(e) => CheckResult::new(
116                name,
117                Errored(format!("failed to check service {sname}: {e}")),
118            ),
119        }
120    }
121}
122
123#[async_trait]
124impl CheckGroup for ServiceChecks {
125    fn id(&self) -> &str {
126        GROUP_IDENTIFIER
127    }
128
129    fn name(&self) -> &str {
130        NAME
131    }
132
133    fn description(&self) -> &str {
134        "Check status of required host services"
135    }
136
137    async fn run(&self) -> CheckGroupResult {
138        self.run_all().await
139    }
140
141    fn category(&self) -> CheckGroupCategory {
142        CheckGroupCategory::Required
143    }
144}