iml_agent/
systemd.rs

1// Copyright (c) 2019 DDN. All rights reserved.
2// Use of this source code is governed by a MIT-style
3// license that can be found in the LICENSE file.
4
5use std::{ffi::OsStr, process::Command, thread, time};
6
7use crate::agent_error::Result;
8
9/// Runs an arbitrary systemctl command
10///
11/// # Arguments
12///
13/// * `xs` - The args to pass to the systemctl call. `xs` Implements `IntoIterator`
14pub fn systemctl_cmd<I, S>(xs: I) -> Result<std::process::Output>
15where
16    I: IntoIterator<Item = S>,
17    S: AsRef<OsStr>,
18{
19    Command::new("systemctl")
20        .args(xs)
21        .output()
22        .map_err(|e| e.into())
23}
24
25/// Starts a service
26///
27/// # Arguments
28///
29/// * `x` - The service to start
30pub fn systemctl_start(x: &str) -> Result<bool> {
31    systemctl_cmd(&["start", x])?;
32
33    for _ in 0..5 {
34        let started = systemctl_status(x).map(did_succeed)?;
35
36        if started {
37            return Ok(started);
38        }
39
40        thread::sleep(time::Duration::from_millis(250));
41    }
42
43    Ok(false)
44}
45
46/// Stops a service
47///
48/// # Arguments
49///
50/// * `x` - The service to stop
51pub fn systemctl_stop(x: &str) -> Result<bool> {
52    systemctl_cmd(&["stop", x])?;
53
54    for _ in 0..5 {
55        let stopped = !systemctl_status(x).map(did_succeed)?;
56
57        if stopped {
58            return Ok(stopped);
59        }
60
61        thread::sleep(time::Duration::from_millis(250));
62    }
63
64    Ok(false)
65}
66
67/// Checks if a service is active
68///
69/// # Arguments
70///
71/// * `x` - The service to check
72pub fn systemctl_status(x: &str) -> Result<std::process::Output> {
73    systemctl_cmd(&["is-active", x, "--quiet"])
74}
75
76/// Invokes `success` on `ExitStatus` within `Output`
77///
78/// # Arguments
79///
80/// * `x` - The `Output` to check
81pub fn did_succeed(x: std::process::Output) -> bool {
82    x.status.success()
83}