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