xref: /DragonReach/src/unit/mod.rs (revision 2069cc0dc0984a2981454b00316ba607f88ac512)
1 use std::any::Any;
2 use std::fmt::Debug;
3 use std::sync::atomic::AtomicUsize;
4 use std::sync::atomic::Ordering;
5 
6 use crate::error::parse_error::ParseError;
7 use crate::error::parse_error::ParseErrorType;
8 use crate::error::runtime_error::RuntimeError;
9 
10 use crate::executor::ExitStatus;
11 use crate::parse::parse_util::UnitParseUtil;
12 use crate::parse::Segment;
13 
14 pub mod service;
15 pub mod target;
16 pub mod timer;
17 
18 use self::target::TargetUnit;
19 
20 pub fn generate_unit_id() -> usize {
21     static UNIT_ID: AtomicUsize = AtomicUsize::new(1);
22     return UNIT_ID.fetch_add(1, Ordering::SeqCst);
23 }
24 
25 //所有可解析的Unit都应该实现该trait
26 pub trait Unit: Sync + Send + Debug {
27     /// @brief 从文件获取到Unit,该函数是解析Unit文件的入口函数
28     ///
29     /// 从path解析Unit属性
30     ///
31     /// @param path 需解析的文件
32     ///
33     /// @return 解析成功则返回对应Unit的id,否则返回Err
34     fn from_path(path: &str) -> Result<usize, ParseError>
35     where
36         Self: Sized;
37 
38     fn as_any(&self) -> &dyn Any;
39 
40     fn as_mut_any(&mut self) -> &mut dyn Any;
41 
42     /// @brief 设置Unit属性
43     ///
44     /// 设置对应Unit属性
45     ///
46     /// @param segment  属性段类型
47     ///
48     /// @param attr     属性名
49     ///
50     /// @param val      属性值
51     ///
52     /// @return 设置成功则返回Ok(()),否则返回Err
53     fn set_attr(&mut self, segment: Segment, attr: &str, val: &str) -> Result<(), ParseError>;
54 
55     /// # 设置每个Unit都应该有的属性
56     ///
57     /// 设置BaseUnit
58     ///
59     /// ## param unit_base  设置值
60     fn set_unit_base(&mut self, unit_base: BaseUnit);
61 
62     /// # 获取UnitType
63     ///
64     /// ## return UnitType
65     fn unit_type(&self) -> UnitType;
66 
67     fn unit_base(&self) -> &BaseUnit;
68 
69     fn unit_base_mut(&mut self) -> &mut BaseUnit;
70 
71     fn unit_id(&self) -> usize;
72 
73     /// ## Unit的工作逻辑
74     ///
75     /// ### return OK(())/Err
76     fn run(&mut self) -> Result<(), RuntimeError>;
77 
78     /// ## 设置unit_id
79     ///
80     /// ### return OK(())/Err
81     fn set_unit_id(&mut self) -> usize {
82         let ret = generate_unit_id();
83         self.unit_base_mut().set_id(ret);
84         ret
85     }
86 
87     /// ## Unit退出后逻辑
88     ///
89     /// 一般只有可运行的Unit(如Service)需要重写此函数
90     fn after_exit(&mut self, _exit_status: ExitStatus) {
91         unimplemented!()
92     }
93 
94     /// ## 初始化Unit内任务的一些参数,各个Unit所需处理的不相同,故放在总的Unit trait
95     fn init(&mut self) {}
96 
97     /// ## Unit的显式退出逻辑
98     fn exit(&mut self);
99 
100     fn set_unit_name(&mut self, name: String) {
101         self.unit_base_mut().unit_name = name;
102     }
103 
104     /// ## Unit重启逻辑
105     fn restart(&mut self) -> Result<(), RuntimeError> {
106         unimplemented!()
107     }
108 }
109 
110 //Unit状态
111 #[allow(dead_code)]
112 #[derive(Clone, Copy, Debug, PartialEq)]
113 pub enum UnitState {
114     Active,
115     Inactive,
116     Activating,
117     Deactivating,
118     Failed,
119     Reloading,
120     Maintenance,
121 }
122 
123 impl ToString for UnitState {
124     fn to_string(&self) -> String {
125         match *self {
126             UnitState::Active => "active".to_string(),
127             UnitState::Inactive => "inactive".to_string(),
128             UnitState::Activating => "activeting".to_string(),
129             UnitState::Deactivating => "deactivating".to_string(),
130             UnitState::Failed => "failed".to_string(),
131             UnitState::Reloading => "reloading".to_string(),
132             UnitState::Maintenance => "maintenance".to_string(),
133         }
134     }
135 }
136 
137 #[allow(dead_code)]
138 #[derive(Clone, Copy, Debug, PartialEq)]
139 pub enum UnitSubState {
140     Running,
141     Waiting,
142     StartPre,
143     StartPost,
144     StopSigterm,
145     StopSigkill,
146     StopFinalSigterm,
147     StopFinalSigkill,
148     Dead,
149     AutoRestart,
150     Failed,
151     Activating,
152     Deactivating,
153     Plugged,
154     Unknown,
155 }
156 
157 impl ToString for UnitSubState {
158     fn to_string(&self) -> String {
159         match *self {
160             UnitSubState::Running => "running".to_string(),
161             UnitSubState::Waiting => "waiting".to_string(),
162             UnitSubState::StartPre => "start-pre".to_string(),
163             UnitSubState::StartPost => "start-post".to_string(),
164             UnitSubState::StopSigterm => "stop-sigterm".to_string(),
165             UnitSubState::StopSigkill => "stop-sigkill".to_string(),
166             UnitSubState::StopFinalSigterm => "stop-final-sigterm".to_string(),
167             UnitSubState::StopFinalSigkill => "stop-final-sigkill".to_string(),
168             UnitSubState::Dead => "dead".to_string(),
169             UnitSubState::AutoRestart => "auto-restart".to_string(),
170             UnitSubState::Failed => "failed".to_string(),
171             UnitSubState::Activating => "activating".to_string(),
172             UnitSubState::Deactivating => "deactivating".to_string(),
173             UnitSubState::Plugged => "plugged".to_string(),
174             UnitSubState::Unknown => "unknown".to_string(),
175         }
176     }
177 }
178 
179 #[allow(dead_code)]
180 #[derive(Clone, Copy, Debug, PartialEq)]
181 pub enum LoadState {
182     Loaded,
183     NotFound,
184     Error,
185     Masked,
186 }
187 
188 impl ToString for LoadState {
189     fn to_string(&self) -> String {
190         match *self {
191             LoadState::Loaded => "loaded".to_string(),
192             LoadState::NotFound => "not found".to_string(),
193             LoadState::Error => "error".to_string(),
194             LoadState::Masked => "maksed".to_string(),
195         }
196     }
197 }
198 
199 //Unit类型
200 #[allow(dead_code)]
201 #[derive(Clone, Copy, PartialEq, Debug)]
202 pub enum UnitType {
203     Automount,
204     Device,
205     Mount,
206     Path,
207     Scope,
208     Service,
209     Slice,
210     Snapshot,
211     Socket,
212     Swap,
213     Target,
214     Timer,
215     Unknown,
216 }
217 
218 //记录unit文件基本信息,这个结构体里面的信息是所有Unit文件都可以有的属性
219 #[allow(dead_code)]
220 #[derive(Debug, Clone)]
221 pub struct BaseUnit {
222     unit_name: String,
223     unit_part: UnitPart,
224     install_part: InstallPart,
225     state: UnitState,
226     sub_state: UnitSubState,
227     load_state: LoadState,
228     unit_type: UnitType,
229     unit_id: usize,
230 }
231 
232 impl Default for BaseUnit {
233     fn default() -> Self {
234         BaseUnit {
235             unit_name: String::new(),
236             unit_part: UnitPart::default(),
237             install_part: InstallPart::default(),
238             state: UnitState::Inactive,
239             sub_state: UnitSubState::Unknown,
240             load_state: LoadState::Loaded,
241             unit_type: UnitType::Unknown,
242             unit_id: 0,
243         }
244     }
245 }
246 
247 #[allow(dead_code)]
248 impl BaseUnit {
249     pub fn set_state(&mut self, state: UnitState) {
250         self.state = state;
251     }
252 
253     pub fn set_unit_type(&mut self, utype: UnitType) {
254         self.unit_type = utype;
255     }
256 
257     pub fn set_unit_part_attr(
258         &mut self,
259         attr_type: &BaseUnitAttr,
260         val: &str,
261     ) -> Result<(), ParseError> {
262         return self.unit_part.set_attr(attr_type, val);
263     }
264 
265     pub fn set_install_part_attr(
266         &mut self,
267         attr_type: &InstallUnitAttr,
268         val: &str,
269     ) -> Result<(), ParseError> {
270         return self.install_part.set_attr(attr_type, val);
271     }
272 
273     pub fn parse_and_set_attribute(&self) -> Result<(), ParseError> {
274         return Ok(());
275     }
276 
277     pub fn unit_part(&self) -> &UnitPart {
278         &self.unit_part
279     }
280 
281     pub fn mut_unit_part(&mut self) -> &mut UnitPart {
282         &mut self.unit_part
283     }
284 
285     pub fn install_part(&self) -> &InstallPart {
286         &self.install_part
287     }
288 
289     pub fn state(&self) -> &UnitState {
290         &self.state
291     }
292 
293     pub fn unit_type(&self) -> &UnitType {
294         &self.unit_type
295     }
296 
297     pub fn set_id(&mut self, id: usize) {
298         self.unit_id = id;
299     }
300 
301     pub fn unit_name(&self) -> String {
302         self.unit_name.clone()
303     }
304 
305     /// ## Unit基本格式化信息
306     pub fn unit_info(&self) -> String {
307         format!(
308             "{}\t\t\t{}\t\t{}\t\t{}\t\t{}",
309             self.unit_name,
310             self.load_state.to_string(),
311             self.state.to_string(),
312             self.sub_state.to_string(),
313             self.unit_part.description
314         )
315     }
316 }
317 
318 #[derive(Default, Debug, Clone)]
319 pub struct Url {
320     pub url_string: String, // pub protocol: String,
321                             // pub host: String,
322                             // pub port: Option<u16>,
323                             // pub path: String,
324                             // pub query: Option<String>,
325                             // pub fragment: Option<String>,
326 }
327 
328 //对应Unit文件的Unit段
329 #[derive(Debug, Clone)]
330 pub struct UnitPart {
331     // Unit描述
332     description: String,
333     // Unit文档
334     documentation: Vec<Url>,
335     // 依赖项,同时与当前Unit启动,任意一个失败,终止该Unit的启动
336     requires: Vec<usize>,
337     // 依赖项,同时与当前Unit启动,不需要考虑其成功与否
338     wants: Vec<usize>,
339     // 该Unit在下列Units启动完成之后才能启动
340     after: Vec<usize>,
341     // after相反的语义
342     before: Vec<usize>,
343     // 与requires类似,但是这些模块任意一个意外结束或者重启时,该Unit也会终止或重启
344     binds_to: Vec<usize>,
345     // 与binds_to类似,但是不会随着当前Unit启动而启动
346     part_of: Vec<usize>,
347     // 启动失败时,需启动的项
348     on_failure: Vec<usize>,
349     // 与当前Unit冲突项
350     conflicts: Vec<usize>,
351     // 与当前Unit绑定的项,当前Unit失败或者重启时这些项也会跟着终止或重启
352     be_binded_by: Vec<usize>,
353 }
354 
355 impl Default for UnitPart {
356     fn default() -> Self {
357         UnitPart {
358             description: String::new(),
359             documentation: Vec::new(),
360             requires: Vec::new(),
361             wants: Vec::new(),
362             after: Vec::new(),
363             before: Vec::new(),
364             binds_to: Vec::new(),
365             part_of: Vec::new(),
366             on_failure: Vec::new(),
367             conflicts: Vec::new(),
368             be_binded_by: Vec::new(),
369         }
370     }
371 }
372 
373 #[allow(dead_code)]
374 impl UnitPart {
375     pub fn set_attr(&mut self, attr: &BaseUnitAttr, val: &str) -> Result<(), ParseError> {
376         match attr {
377             BaseUnitAttr::None => {
378                 return Err(ParseError::new(
379                     ParseErrorType::ESyntaxError,
380                     String::new(),
381                     0,
382                 ));
383             }
384             BaseUnitAttr::Description => self.description = String::from(val),
385             BaseUnitAttr::Documentation => {
386                 self.documentation.extend(UnitParseUtil::parse_url(val)?)
387             }
388             BaseUnitAttr::Requires => {
389                 let units = val.split_whitespace().collect::<Vec<&str>>();
390                 //TODO:目前先加入requires列表,可能会出现循环依赖问题,后续应解决循环依赖问题
391                 for unit_path in units {
392                     self.requires
393                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
394                 }
395             }
396             BaseUnitAttr::Wants => {
397                 let units = val.split_whitespace().collect::<Vec<&str>>();
398                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
399                 for unit_path in units {
400                     self.wants
401                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
402                 }
403             }
404             BaseUnitAttr::After => {
405                 let units = val.split_whitespace().collect::<Vec<&str>>();
406                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
407                 for unit_path in units {
408                     self.after
409                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
410                 }
411             }
412             BaseUnitAttr::Before => {
413                 let units = val.split_whitespace().collect::<Vec<&str>>();
414                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
415                 for unit_path in units {
416                     self.before
417                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
418                 }
419             }
420             BaseUnitAttr::BindsTo => {
421                 let units = val.split_whitespace().collect::<Vec<&str>>();
422                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
423                 for unit_path in units {
424                     self.binds_to
425                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
426                 }
427             }
428             BaseUnitAttr::PartOf => {
429                 let units = val.split_whitespace().collect::<Vec<&str>>();
430                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
431                 for unit_path in units {
432                     self.part_of
433                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
434                 }
435             }
436             BaseUnitAttr::OnFailure => {
437                 let units = val.split_whitespace().collect::<Vec<&str>>();
438                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
439                 for unit_path in units {
440                     self.on_failure
441                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
442                 }
443             }
444             BaseUnitAttr::Conflicts => {
445                 let units = val.split_whitespace().collect::<Vec<&str>>();
446                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
447                 for unit_path in units {
448                     let unit = UnitParseUtil::parse_unit_no_type(unit_path)?;
449                     self.conflicts.push(unit);
450                 }
451             }
452         }
453         return Ok(());
454     }
455 
456     pub fn description(&self) -> &str {
457         &self.description
458     }
459 
460     pub fn documentation(&self) -> &[Url] {
461         &self.documentation
462     }
463 
464     pub fn requires(&self) -> &[usize] {
465         &self.requires
466     }
467 
468     pub fn wants(&self) -> &[usize] {
469         &self.wants
470     }
471 
472     pub fn after(&self) -> &[usize] {
473         &self.after
474     }
475 
476     pub fn before(&self) -> &[usize] {
477         &self.before
478     }
479 
480     pub fn binds_to(&self) -> &[usize] {
481         &self.binds_to
482     }
483 
484     pub fn part_of(&self) -> &[usize] {
485         &self.part_of
486     }
487 
488     pub fn on_failure(&self) -> &[usize] {
489         &self.on_failure
490     }
491 
492     pub fn conflicts(&self) -> &[usize] {
493         &self.conflicts
494     }
495 
496     pub fn be_binded_by(&self) -> &[usize] {
497         &self.be_binded_by
498     }
499 
500     pub fn push_be_binded_by(&mut self, id: usize) {
501         if !self.be_binded_by.contains(&id) {
502             self.be_binded_by.push(id);
503         }
504     }
505 
506     pub fn push_after_unit(&mut self, id: usize) {
507         if !self.after.contains(&id) {
508             self.after.push(id);
509         }
510     }
511 }
512 
513 //对应Unit文件的Install段
514 #[derive(Debug, Clone)]
515 pub struct InstallPart {
516     wanted_by: Vec<usize>,
517     requires_by: Vec<usize>,
518     also: Vec<usize>,
519     alias: String,
520 }
521 
522 impl Default for InstallPart {
523     fn default() -> Self {
524         InstallPart {
525             wanted_by: Vec::new(),
526             requires_by: Vec::new(),
527             also: Vec::new(),
528             alias: String::new(),
529         }
530     }
531 }
532 
533 #[allow(dead_code)]
534 impl InstallPart {
535     pub fn set_attr(&mut self, attr: &InstallUnitAttr, val: &str) -> Result<(), ParseError> {
536         match attr {
537             InstallUnitAttr::RequiredBy => {
538                 let units = val.split_whitespace().collect::<Vec<&str>>();
539                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
540                 for unit_path in units {
541                     let unit = UnitParseUtil::parse_unit::<TargetUnit>(unit_path)?;
542                     self.requires_by.push(unit);
543                 }
544             }
545             InstallUnitAttr::Also => {
546                 let units = val.split_whitespace().collect::<Vec<&str>>();
547                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
548                 for unit_path in units {
549                     let unit = UnitParseUtil::parse_unit_no_type(unit_path)?;
550                     self.also.push(unit);
551                 }
552             }
553             InstallUnitAttr::WantedBy => {
554                 let units = val.split_whitespace().collect::<Vec<&str>>();
555                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
556                 for unit_path in units {
557                     let unit = UnitParseUtil::parse_unit::<TargetUnit>(unit_path)?;
558                     self.wanted_by.push(unit);
559                 }
560             }
561             InstallUnitAttr::Alias => {
562                 self.alias = String::from(val);
563             }
564             InstallUnitAttr::None => {
565                 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
566             }
567         }
568         return Ok(());
569     }
570 
571     pub fn wanted_by(&self) -> &[usize] {
572         &self.wanted_by
573     }
574 
575     pub fn requires_by(&self) -> &[usize] {
576         &self.requires_by
577     }
578 
579     pub fn also(&self) -> &[usize] {
580         &self.also
581     }
582 
583     pub fn alias(&self) -> &str {
584         &self.alias
585     }
586 }
587 //对应Unit文件的各种属性
588 #[allow(dead_code)]
589 pub enum BaseUnitAttr {
590     None,
591 
592     //Unit段
593     //描述该Unit文件的信息
594     Description,
595     //指定服务文档
596     Documentation,
597     //依赖的其它 Unit 列表
598     Requires,
599     //这个 Unit 启动时,触发启动列出的每个 Unit 模块,而不去考虑这些模板启动是否成功
600     Wants,
601     //后面列出的所有模块全部启动完成以后,才会启动当前的服务
602     After,
603     //在启动指定的任务一个模块之间,都会首先确证当前服务已经运行
604     Before,
605     //这些Unit启动失败时该任务失败,都成功时该任务成功,在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启
606     BindsTo,
607     //仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动
608     PartOf,
609     //当这个模板启动失败时,就会自动启动列出的每个模块
610     OnFailure,
611     //与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然
612     Conflicts,
613 }
614 
615 #[allow(dead_code)]
616 pub enum InstallUnitAttr {
617     None,
618     //Install段
619     //依赖当前服务的模块。当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .wants 后缀构成的子目录中
620     WantedBy,
621     //依赖当前服务的模块。当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .required 后缀构成的子目录中
622     RequiredBy,
623     //当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit
624     Also,
625     //别名
626     Alias,
627 }
628