]>
git.proxmox.com Git - proxmox-backup.git/blob - src/api2/node/services.rs
4 use crate::api_schema
::*;
5 use crate::api_schema
::router
::*;
6 use serde_json
::{json, Value}
;
9 use std
::process
::{Command, Stdio}
;
11 use crate::api2
::types
::*;
13 static SERVICE_NAME_LIST
: [&str; 7] = [
15 "proxmox-backup-proxy",
23 fn real_service_name(service
: &str) -> &str {
25 // since postfix package 3.1.0-3.1 the postfix unit is only here
26 // to manage subinstances, of which the default is called "-".
27 // This is where we look for the daemon status
29 if service
== "postfix" {
36 fn get_full_service_state(service
: &str) -> Result
<Value
, Error
> {
38 let real_service_name
= real_service_name(service
);
40 let mut child
= Command
::new("/bin/systemctl")
41 .args(&["show", real_service_name
])
42 .stdout(Stdio
::piped())
45 use std
::io
::{BufRead,BufReader}
;
47 let mut result
= json
!({}
);
49 if let Some(ref mut stdout
) = child
.stdout
{
50 for line
in BufReader
::new(stdout
).lines() {
53 let mut iter
= line
.splitn(2, '
='
);
54 let key
= iter
.next();
55 let value
= iter
.next();
56 if let (Some(key
), Some(value
)) = (key
, value
) {
57 result
[key
] = Value
::from(value
);
61 log
::error
!("reading service config failed: {}", err
);
69 let status
= child
.wait().unwrap();
70 if !status
.success() {
71 bail
!("systemctl show failed with {}", status
);
77 fn json_service_state(service
: &str, status
: Value
) -> Value
{
79 if let Some(desc
) = status
["Description"].as_str() {
80 let name
= status
["Name"].as_str().unwrap_or(service
);
81 let state
= status
["SubState"].as_str().unwrap_or("unknown");
97 _rpcenv
: &mut dyn RpcEnvironment
,
98 ) -> Result
<Value
, Error
> {
100 let mut list
= vec
![];
102 for service
in &SERVICE_NAME_LIST
{
103 match get_full_service_state(service
) {
105 let state
= json_service_state(service
, status
);
106 if state
!= Value
::Null
{
110 Err(err
) => log
::error
!("{}", err
),
114 Ok(Value
::from(list
))
117 fn get_service_state(
120 _rpcenv
: &mut dyn RpcEnvironment
,
121 ) -> Result
<Value
, Error
> {
123 let service
= tools
::required_string_param(¶m
, "service")?
;
125 if !SERVICE_NAME_LIST
.contains(&service
) {
126 bail
!("unknown service name '{}'", service
);
129 let status
= get_full_service_state(service
)?
;
131 Ok(json_service_state(service
, status
))
134 fn run_service_command(service
: &str, cmd
: &str) -> Result
<Value
, Error
> {
136 // fixme: run background worker (fork_worker) ???
139 "start"|"stop"|"restart"|"reload" => {}
,
140 _
=> bail
!("unknown service command '{}'", cmd
),
143 if service
== "proxmox-backup" {
144 if cmd
!= "restart" {
145 bail
!("invalid service cmd '{} {}'", service
, cmd
);
149 let real_service_name
= real_service_name(service
);
151 let status
= Command
::new("/bin/systemctl")
152 .args(&[cmd
, real_service_name
])
155 if !status
.success() {
156 bail
!("systemctl {} failed with {}", cmd
, status
);
165 _rpcenv
: &mut dyn RpcEnvironment
,
166 ) -> Result
<Value
, Error
> {
168 let service
= tools
::required_string_param(¶m
, "service")?
;
170 log
::info
!("starting service {}", service
);
172 run_service_command(service
, "start")
178 _rpcenv
: &mut dyn RpcEnvironment
,
179 ) -> Result
<Value
, Error
> {
181 let service
= tools
::required_string_param(¶m
, "service")?
;
183 log
::info
!("stoping service {}", service
);
185 run_service_command(service
, "stop")
191 _rpcenv
: &mut dyn RpcEnvironment
,
192 ) -> Result
<Value
, Error
> {
194 let service
= tools
::required_string_param(¶m
, "service")?
;
196 log
::info
!("re-starting service {}", service
);
198 if service
== "proxmox-backup-proxy" {
199 // special case, avoid aborting running tasks
200 run_service_command(service
, "reload")
202 run_service_command(service
, "restart")
209 _rpcenv
: &mut dyn RpcEnvironment
,
210 ) -> Result
<Value
, Error
> {
212 let service
= tools
::required_string_param(¶m
, "service")?
;
214 log
::info
!("reloading service {}", service
);
216 run_service_command(service
, "reload")
219 pub fn router() -> Router
{
221 let service_id_schema
: Arc
<Schema
> = Arc
::new(
222 StringSchema
::new("Service ID.")
227 let service_api
= Router
::new()
233 ObjectSchema
::new("Read service properties.")
234 .required("node", NODE_SCHEMA
.clone())
235 .required("service", service_id_schema
.clone()))
244 ObjectSchema
::new("Start service.")
245 .required("node", NODE_SCHEMA
.clone())
246 .required("service", service_id_schema
.clone())
256 ObjectSchema
::new("Stop service.")
257 .required("node", NODE_SCHEMA
.clone())
258 .required("service", service_id_schema
.clone())
268 ObjectSchema
::new("Restart service.")
269 .required("node", NODE_SCHEMA
.clone())
270 .required("service", service_id_schema
.clone())
280 ObjectSchema
::new("Reload service.")
281 .required("node", NODE_SCHEMA
.clone())
282 .required("service", service_id_schema
.clone())
288 let route
= Router
::new()
292 ObjectSchema
::new("Service list.")
293 .required("node", NODE_SCHEMA
.clone())
296 "Returns a list of systemd services.",
297 ObjectSchema
::new("Service details.")
298 .required("service", service_id_schema
.clone())
299 .required("name", StringSchema
::new("systemd service name."))
300 .required("desc", StringSchema
::new("systemd service description."))
301 .required("state", StringSchema
::new("systemd service 'SubState'."))
306 .match_all("service", service_api
);