]>
git.proxmox.com Git - proxmox-backup.git/blob - src/api2/node/services.rs
4 use crate::api
::schema
::*;
5 use crate::api
::router
::*;
6 use serde_json
::{json, Value}
;
9 use lazy_static
::lazy_static
;
10 use crate::tools
::common_regex
;
11 use std
::process
::{Command, Stdio}
;
13 static SERVICE_NAME_LIST
: [&str; 6] = [
22 fn real_service_name(service
: &str) -> &str {
24 // since postfix package 3.1.0-3.1 the postfix unit is only here
25 // to manage subinstances, of which the default is called "-".
26 // This is where we look for the daemon status
28 if service
== "postfix" {
35 fn get_full_service_state(service
: &str) -> Result
<Value
, Error
> {
37 let real_service_name
= real_service_name(service
);
39 let mut child
= Command
::new("/bin/systemctl")
40 .args(&["show", real_service_name
])
41 .stdout(Stdio
::piped())
44 use std
::io
::{BufRead,BufReader}
;
46 let mut result
= json
!({}
);
48 if let Some(ref mut stdout
) = child
.stdout
{
49 for line
in BufReader
::new(stdout
).lines() {
52 let mut iter
= line
.splitn(2, '
='
);
53 let key
= iter
.next();
54 let value
= iter
.next();
55 if let (Some(key
), Some(value
)) = (key
, value
) {
56 result
[key
] = Value
::from(value
);
60 log
::error
!("reading service config failed: {}", err
);
68 let status
= child
.wait().unwrap();
69 if !status
.success() {
70 bail
!("systemctl show failed with {}", status
);
76 fn json_service_state(service
: &str, status
: Value
) -> Value
{
78 if let Some(desc
) = status
["Description"].as_str() {
79 let name
= status
["Name"].as_str().unwrap_or(service
);
80 let state
= status
["SubState"].as_str().unwrap_or("unknown");
96 rpcenv
: &mut RpcEnvironment
,
97 ) -> Result
<Value
, Error
> {
99 let mut list
= vec
![];
101 for service
in &SERVICE_NAME_LIST
{
102 match get_full_service_state(service
) {
104 let state
= json_service_state(service
, status
);
105 if state
!= Value
::Null
{
109 Err(err
) => log
::error
!("{}", err
),
113 Ok(Value
::from(list
))
116 fn get_service_state(
119 rpcenv
: &mut RpcEnvironment
,
120 ) -> Result
<Value
, Error
> {
122 let service
= tools
::required_string_param(¶m
, "service")?
;
124 if !SERVICE_NAME_LIST
.contains(&service
) {
125 bail
!("unknown service name '{}'", service
);
128 let status
= get_full_service_state(service
)?
;
130 Ok(json_service_state(service
, status
))
133 fn run_service_command(service
: &str, cmd
: &str) -> Result
<Value
, Error
> {
135 // fixme: run background worker (fork_worker) ???
138 "start"|"stop"|"restart"|"reload" => {}
,
139 _
=> bail
!("unknown service command '{}'", cmd
),
142 if service
== "proxmox-backup" {
143 if cmd
!= "restart" {
144 bail
!("invalid service cmd '{} {}'", service
, cmd
);
148 let real_service_name
= real_service_name(service
);
150 let status
= Command
::new("/bin/systemctl")
151 .args(&[cmd
, real_service_name
])
154 if !status
.success() {
155 bail
!("systemctl {} failed with {}", cmd
, status
);
164 rpcenv
: &mut RpcEnvironment
,
165 ) -> Result
<Value
, Error
> {
167 let service
= tools
::required_string_param(¶m
, "service")?
;
169 log
::info
!("starting service {}", service
);
171 run_service_command(service
, "start")
177 rpcenv
: &mut RpcEnvironment
,
178 ) -> Result
<Value
, Error
> {
180 let service
= tools
::required_string_param(¶m
, "service")?
;
182 log
::info
!("stoping service {}", service
);
184 run_service_command(service
, "stop")
190 rpcenv
: &mut RpcEnvironment
,
191 ) -> Result
<Value
, Error
> {
193 let service
= tools
::required_string_param(¶m
, "service")?
;
195 log
::info
!("re-starting service {}", service
);
197 run_service_command(service
, "restart")
203 rpcenv
: &mut RpcEnvironment
,
204 ) -> Result
<Value
, Error
> {
206 let service
= tools
::required_string_param(¶m
, "service")?
;
208 log
::info
!("reloading service {}", service
);
210 run_service_command(service
, "reload")
213 pub fn router() -> Router
{
215 let service_id_schema
: Arc
<Schema
> = Arc
::new(
216 StringSchema
::new("Service ID.")
221 let service_api
= Router
::new()
224 let mut result
= vec
![];
225 for cmd
in &["state", "start", "stop", "restart", "reload"] {
226 result
.push(json
!({"subdir": cmd }
));
228 Ok(Value
::from(result
))
230 ObjectSchema
::new("Directory index.")
231 .required("service", service_id_schema
.clone()))
238 ObjectSchema
::new("Read service properties.")
239 .required("service", service_id_schema
.clone()))
245 .post(ApiMethod
::new(
247 ObjectSchema
::new("Start service.")
248 .required("service", service_id_schema
.clone()))
254 .post(ApiMethod
::new(
256 ObjectSchema
::new("Stop service.")
257 .required("service", service_id_schema
.clone()))
263 .post(ApiMethod
::new(
265 ObjectSchema
::new("Restart service.")
266 .required("service", service_id_schema
.clone()))
272 .post(ApiMethod
::new(
274 ObjectSchema
::new("Reload service.")
275 .required("service", service_id_schema
.clone()))
280 let route
= Router
::new()
284 ObjectSchema
::new("Service list.")
287 "Returns a list of systemd services.",
288 ObjectSchema
::new("Service details.")
289 .required("service", service_id_schema
.clone())
290 .required("name", StringSchema
::new("systemd service name."))
291 .required("desc", StringSchema
::new("systemd service description."))
292 .required("state", StringSchema
::new("systemd service 'SubState'."))
297 .match_all("service", service_api
);