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