xref: /DragonReach/src/unit/service/mod.rs (revision b58bd5a17ff5d5ea5385adc176e215cd2b9a485c)
1 use super::{BaseUnit, Unit};
2 use crate::error::{ParseError, ParseErrorType};
3 use crate::parse::parse_service::ServiceParser;
4 use crate::parse::parse_util::UnitParseUtil;
5 use crate::parse::{Segment, SERVICE_UNIT_ATTR_TABLE};
6 use crate::task::cmdtask::CmdTask;
7 
8 #[cfg(target_os = "dragonos")]
9 use drstd as std;
10 use std::rc::Rc;
11 use std::string::String;
12 use std::vec::Vec;
13 #[derive(Default)]
14 pub struct ServiceUnit {
15     unit_base: BaseUnit,
16     service_part: ServicePart,
17 }
18 
19 #[derive(Debug)]
20 pub enum ServiceType {
21     Simple,
22     Forking,
23     OneShot,
24     Dbus,
25     Notify,
26     Idle,
27 }
28 
29 impl Default for ServiceType {
30     fn default() -> Self {
31         ServiceType::Simple
32     }
33 }
34 
35 #[derive(Debug)]
36 pub enum RestartOption {
37     AlwaysRestart,
38     OnSuccess,
39     OnFailure,
40     OnAbnormal,
41     OnAbort,
42     OnWatchdog,
43     None,
44 }
45 
46 impl Default for RestartOption {
47     fn default() -> Self {
48         Self::None
49     }
50 }
51 
52 #[derive(Debug)]
53 pub enum MountFlag {
54     Shared,
55     Slave,
56     Private,
57 }
58 
59 impl Default for MountFlag {
60     fn default() -> Self {
61         Self::Private
62     }
63 }
64 
65 #[derive(Default, Debug)]
66 pub struct ServicePart {
67     //生命周期相关
68     service_type: ServiceType,
69     ///
70     remain_after_exit: bool,
71     exec_start: Vec<CmdTask>,
72     exec_start_pre: Vec<CmdTask>,
73     exec_start_pos: Vec<CmdTask>,
74     exec_reload: Vec<CmdTask>,
75     exec_stop: Vec<CmdTask>,
76     exec_stop_post: Vec<CmdTask>,
77     restart_sec: u64,
78     restart: RestartOption,
79     timeout_start_sec: u64,
80     timeout_stop_sec: u64,
81     //上下文配置相关
82     environment: Vec<String>,
83     environment_file: String,
84     nice: i8,
85     working_directory: String,
86     root_directory: String,
87     user: String,
88     group: String,
89     mount_flags: MountFlag,
90     //LimitCPU / LimitSTACK / LimitNOFILE / LimitNPROC 等,后续支持再添加
91 }
92 
93 impl Unit for ServiceUnit {
94     fn as_any(&self) -> &dyn core::any::Any {
95         self
96     }
97 
98     fn from_path(path: &str) -> Result<Rc<Self>, ParseError>
99     where
100         Self: Sized,
101     {
102         return ServiceParser::parse(path);
103     }
104 
105     fn set_attr(&mut self, segment: Segment, attr: &str, val: &str) -> Result<(), ParseError> {
106         if segment != Segment::Service {
107             return Err(ParseError::new(ParseErrorType::EINVAL, String::new(),0));
108         }
109         let attr_type = SERVICE_UNIT_ATTR_TABLE.get(attr).ok_or(ParseError::new(ParseErrorType::EINVAL, String::new(),0));
110         return self.service_part.set_attr(attr_type.unwrap(), val);
111     }
112 
113     fn set_unit_base(&mut self, base: BaseUnit) {
114         self.unit_base = base;
115     }
116 
117     fn unit_type(&self) -> super::UnitType {
118         return self.unit_base.unit_type;
119     }
120 }
121 
122 impl ServiceUnit {
123     pub fn unit_base(&self) -> &BaseUnit {
124         return &self.unit_base;
125     }
126 
127     pub fn service_part(&self) -> &ServicePart {
128         return &self.service_part;
129     }
130 }
131 
132 pub enum ServiceUnitAttr {
133     None,
134     //Service段
135     //定义启动时的进程行为
136     Type,
137     //
138     RemainAfterExit,
139     //启动命令
140     ExecStart,
141     //启动当前服务之前执行的命令
142     ExecStartPre,
143     //启动当前服务之后执行的命令
144     ExecStartPos,
145     //重启当前服务时执行的命令
146     ExecReload,
147     //停止当前服务时执行的命令
148     ExecStop,
149     //停止当其服务之后执行的命令
150     ExecStopPost,
151     //自动重启当前服务间隔的秒数
152     RestartSec,
153     //定义何种情况 Systemd 会自动重启当前服务
154     Restart,
155     //启动服务时等待的秒数
156     TimeoutStartSec,
157     //停止服务时的等待秒数,如果超过这个时间仍然没有停止,应该使用 SIGKILL 信号强行杀死服务的进程
158     TimeoutStopSec,
159     //为服务指定环境变量
160     Environment,
161     //指定加载一个包含服务所需的环境变量的列表的文件,文件中的每一行都是一个环境变量的定义
162     EnvironmentFile,
163     //服务的进程优先级,值越小优先级越高,默认为 0。其中 -20 为最高优先级,19 为最低优先级
164     Nice,
165     //指定服务的工作目录
166     WorkingDirectory,
167     //指定服务进程的根目录(/ 目录)。如果配置了这个参数,服务将无法访问指定目录以外的任何文件
168     RootDirectory,
169     //指定运行服务的用户
170     User,
171     //指定运行服务的用户组
172     Group,
173     //服务的 Mount Namespace 配置,会影响进程上下文中挂载点的信息
174     MountFlags,
175 }
176 
177 impl ServicePart {
178     pub fn set_attr(&mut self, attr: &ServiceUnitAttr, val: &str) -> Result<(), ParseError> {
179         match attr {
180             ServiceUnitAttr::Type => match val {
181                 "simple" => self.service_type = ServiceType::Simple,
182                 "forking" => self.service_type = ServiceType::Forking,
183                 "oneshot" => self.service_type = ServiceType::OneShot,
184                 "dbus" => self.service_type = ServiceType::Dbus,
185                 "notify" => self.service_type = ServiceType::Notify,
186                 "idle" => self.service_type = ServiceType::Idle,
187                 _ => {
188                     return Err(ParseError::new(ParseErrorType::EINVAL, String::new(),0));
189                 }
190             },
191             ServiceUnitAttr::RemainAfterExit => {
192                 self.remain_after_exit = UnitParseUtil::parse_boolean(val)?
193             }
194             ServiceUnitAttr::ExecStart => {
195                 self.exec_start.extend(UnitParseUtil::parse_cmd_task(val)?);
196             }
197             ServiceUnitAttr::ExecStartPre => {
198                 self.exec_start_pre
199                     .extend(UnitParseUtil::parse_cmd_task(val)?);
200             }
201             ServiceUnitAttr::ExecStartPos => {
202                 self.exec_start_pos
203                     .extend(UnitParseUtil::parse_cmd_task(val)?);
204             }
205             ServiceUnitAttr::ExecReload => {
206                 self.exec_reload.extend(UnitParseUtil::parse_cmd_task(val)?);
207             }
208             ServiceUnitAttr::ExecStopPost => {
209                 self.exec_stop_post
210                     .extend(UnitParseUtil::parse_cmd_task(val)?);
211             }
212             ServiceUnitAttr::ExecStop => {
213                 self.exec_stop.extend(UnitParseUtil::parse_cmd_task(val)?);
214             }
215             ServiceUnitAttr::RestartSec => self.restart_sec = UnitParseUtil::parse_sec(val)?,
216             ServiceUnitAttr::Restart => match val {
217                 "always" => self.restart = RestartOption::AlwaysRestart,
218                 "on-success" => self.restart = RestartOption::OnSuccess,
219                 "on-failure" => self.restart = RestartOption::OnFailure,
220                 "on-abnormal" => self.restart = RestartOption::OnAbnormal,
221                 "on-abort" => self.restart = RestartOption::OnAbort,
222                 "on-watchdog" => self.restart = RestartOption::OnWatchdog,
223                 _ => {
224                     return Err(ParseError::new(ParseErrorType::EINVAL,String::new(),0));
225                 }
226             },
227             ServiceUnitAttr::TimeoutStartSec => {
228                 self.timeout_start_sec = UnitParseUtil::parse_sec(val)?
229             }
230             ServiceUnitAttr::TimeoutStopSec => {
231                 self.timeout_stop_sec = UnitParseUtil::parse_sec(val)?
232             }
233             ServiceUnitAttr::Environment => {
234                 self.environment.push(String::from(val));
235             }
236             ServiceUnitAttr::EnvironmentFile => {
237                 if !UnitParseUtil::is_valid_file(val) {
238                     return Err(ParseError::new(ParseErrorType::EFILE,String::new(),0));
239                 }
240                 self.environment_file = String::from(val);
241             }
242             ServiceUnitAttr::Nice => {
243                 self.nice = UnitParseUtil::parse_nice(val)?;
244             }
245             ServiceUnitAttr::WorkingDirectory => {
246                 if !UnitParseUtil::is_dir(val) {
247                     return Err(ParseError::new(ParseErrorType::ENODIR,String::new(),0));
248                 }
249                 self.working_directory = String::from(val);
250             }
251             ServiceUnitAttr::User => {
252                 //TODO: 检查系统是否存在这个用户
253                 self.user = String::from(val);
254             }
255             ServiceUnitAttr::Group => {
256                 //TODO: 检查系统是否存在该用户组
257                 self.group = String::from(val);
258             }
259             ServiceUnitAttr::MountFlags => match val {
260                 "shared" => self.mount_flags = MountFlag::Shared,
261                 "slave" => self.mount_flags = MountFlag::Slave,
262                 "private" => self.mount_flags = MountFlag::Private,
263                 _ => {
264                     return Err(ParseError::new(ParseErrorType::EINVAL,String::new(),0));
265                 }
266             },
267             _ => {
268                 return Err(ParseError::new(ParseErrorType::EINVAL,String::new(),0));
269             }
270         }
271         return Ok(());
272     }
273 
274     // 生命周期相关
275     pub fn service_type(&self) -> &ServiceType {
276         &self.service_type
277     }
278 
279     pub fn remain_after_exit(&self) -> bool {
280         self.remain_after_exit
281     }
282 
283     pub fn exec_start(&self) -> &Vec<CmdTask> {
284         &self.exec_start
285     }
286 
287     pub fn exec_start_pre(&self) -> &Vec<CmdTask> {
288         &self.exec_start_pre
289     }
290 
291     pub fn exec_start_pos(&self) -> &Vec<CmdTask> {
292         &self.exec_start_pos
293     }
294 
295     pub fn exec_reload(&self) -> &Vec<CmdTask> {
296         &self.exec_reload
297     }
298 
299     pub fn exec_stop(&self) -> &Vec<CmdTask> {
300         &self.exec_stop
301     }
302 
303     pub fn exec_stop_post(&self) -> &Vec<CmdTask> {
304         &self.exec_stop_post
305     }
306 
307     pub fn restart_sec(&self) -> u64 {
308         self.restart_sec
309     }
310 
311     pub fn restart(&self) -> &RestartOption {
312         &self.restart
313     }
314 
315     pub fn timeout_start_sec(&self) -> u64 {
316         self.timeout_start_sec
317     }
318 
319     pub fn timeout_stop_sec(&self) -> u64 {
320         self.timeout_stop_sec
321     }
322 
323     // 上下文配置相关
324     pub fn environment(&self) -> &[String] {
325         &self.environment
326     }
327 
328     pub fn environment_file(&self) -> &str {
329         &self.environment_file
330     }
331 
332     pub fn nice(&self) -> i8 {
333         self.nice
334     }
335 
336     pub fn working_directory(&self) -> &str {
337         &self.working_directory
338     }
339 
340     pub fn root_directory(&self) -> &str {
341         &self.root_directory
342     }
343 
344     pub fn user(&self) -> &str {
345         &self.user
346     }
347 
348     pub fn group(&self) -> &str {
349         &self.group
350     }
351 
352     pub fn mount_flags(&self) -> &MountFlag {
353         &self.mount_flags
354     }
355 }
356