]>
git.proxmox.com Git - proxmox-backup.git/blob - src/api2/node/services.rs
4 use crate::api_schema
::schema
::*;
5 use crate::api_schema
::router
::*;
6 use serde_json
::{json, Value}
;
9 use std
::process
::{Command, Stdio}
;
11 static SERVICE_NAME_LIST
: [&str; 6] = [
20 fn real_service_name(service
: &str) -> &str {
22 // since postfix package 3.1.0-3.1 the postfix unit is only here
23 // to manage subinstances, of which the default is called "-".
24 // This is where we look for the daemon status
26 if service
== "postfix" {
33 fn get_full_service_state(service
: &str) -> Result
<Value
, Error
> {
35 let real_service_name
= real_service_name(service
);
37 let mut child
= Command
::new("/bin/systemctl")
38 .args(&["show", real_service_name
])
39 .stdout(Stdio
::piped())
42 use std
::io
::{BufRead,BufReader}
;
44 let mut result
= json
!({}
);
46 if let Some(ref mut stdout
) = child
.stdout
{
47 for line
in BufReader
::new(stdout
).lines() {
50 let mut iter
= line
.splitn(2, '
='
);
51 let key
= iter
.next();
52 let value
= iter
.next();
53 if let (Some(key
), Some(value
)) = (key
, value
) {
54 result
[key
] = Value
::from(value
);
58 log
::error
!("reading service config failed: {}", err
);
66 let status
= child
.wait().unwrap();
67 if !status
.success() {
68 bail
!("systemctl show failed with {}", status
);
74 fn json_service_state(service
: &str, status
: Value
) -> Value
{
76 if let Some(desc
) = status
["Description"].as_str() {
77 let name
= status
["Name"].as_str().unwrap_or(service
);
78 let state
= status
["SubState"].as_str().unwrap_or("unknown");
94 _rpcenv
: &mut RpcEnvironment
,
95 ) -> Result
<Value
, Error
> {
97 let mut list
= vec
![];
99 for service
in &SERVICE_NAME_LIST
{
100 match get_full_service_state(service
) {
102 let state
= json_service_state(service
, status
);
103 if state
!= Value
::Null
{
107 Err(err
) => log
::error
!("{}", err
),
111 Ok(Value
::from(list
))
114 fn get_service_state(
117 _rpcenv
: &mut RpcEnvironment
,
118 ) -> Result
<Value
, Error
> {
120 let service
= tools
::required_string_param(¶m
, "service")?
;
122 if !SERVICE_NAME_LIST
.contains(&service
) {
123 bail
!("unknown service name '{}'", service
);
126 let status
= get_full_service_state(service
)?
;
128 Ok(json_service_state(service
, status
))
131 fn run_service_command(service
: &str, cmd
: &str) -> Result
<Value
, Error
> {
133 // fixme: run background worker (fork_worker) ???
136 "start"|"stop"|"restart"|"reload" => {}
,
137 _
=> bail
!("unknown service command '{}'", cmd
),
140 if service
== "proxmox-backup" {
141 if cmd
!= "restart" {
142 bail
!("invalid service cmd '{} {}'", service
, cmd
);
146 let real_service_name
= real_service_name(service
);
148 let status
= Command
::new("/bin/systemctl")
149 .args(&[cmd
, real_service_name
])
152 if !status
.success() {
153 bail
!("systemctl {} failed with {}", cmd
, status
);
162 _rpcenv
: &mut RpcEnvironment
,
163 ) -> Result
<Value
, Error
> {
165 let service
= tools
::required_string_param(¶m
, "service")?
;
167 log
::info
!("starting service {}", service
);
169 run_service_command(service
, "start")
175 _rpcenv
: &mut RpcEnvironment
,
176 ) -> Result
<Value
, Error
> {
178 let service
= tools
::required_string_param(¶m
, "service")?
;
180 log
::info
!("stoping service {}", service
);
182 run_service_command(service
, "stop")
188 _rpcenv
: &mut RpcEnvironment
,
189 ) -> Result
<Value
, Error
> {
191 let service
= tools
::required_string_param(¶m
, "service")?
;
193 log
::info
!("re-starting service {}", service
);
195 run_service_command(service
, "restart")
201 _rpcenv
: &mut RpcEnvironment
,
202 ) -> Result
<Value
, Error
> {
204 let service
= tools
::required_string_param(¶m
, "service")?
;
206 log
::info
!("reloading service {}", service
);
208 run_service_command(service
, "reload")
211 pub fn router() -> Router
{
213 let service_id_schema
: Arc
<Schema
> = Arc
::new(
214 StringSchema
::new("Service ID.")
219 let service_api
= Router
::new()
222 let mut result
= vec
![];
223 for cmd
in &["state", "start", "stop", "restart", "reload"] {
224 result
.push(json
!({"subdir": cmd }
));
226 Ok(Value
::from(result
))
228 ObjectSchema
::new("Directory index.")
229 .required("service", service_id_schema
.clone()))
236 ObjectSchema
::new("Read service properties.")
237 .required("service", service_id_schema
.clone()))
246 ObjectSchema
::new("Start service.")
247 .required("service", service_id_schema
.clone())
257 ObjectSchema
::new("Stop service.")
258 .required("service", service_id_schema
.clone())
268 ObjectSchema
::new("Restart service.")
269 .required("service", service_id_schema
.clone())
279 ObjectSchema
::new("Reload service.")
280 .required("service", service_id_schema
.clone())
286 let route
= Router
::new()
290 ObjectSchema
::new("Service list.")
293 "Returns a list of systemd services.",
294 ObjectSchema
::new("Service details.")
295 .required("service", service_id_schema
.clone())
296 .required("name", StringSchema
::new("systemd service name."))
297 .required("desc", StringSchema
::new("systemd service description."))
298 .required("state", StringSchema
::new("systemd service 'SubState'."))
303 .match_all("service", service_api
);