xref: /DragonReach/src/unit/mod.rs (revision b58bd5a17ff5d5ea5385adc176e215cd2b9a485c)
1 use crate::error::ParseError;
2 use crate::error::ParseErrorType;
3 use crate::parse::parse_util::UnitParseUtil;
4 use crate::parse::Segment;
5 
6 #[cfg(target_os = "dragonos")]
7 use drstd as std;
8 
9 use std::any::Any;
10 use std::boxed::Box;
11 use std::default::Default;
12 use std::rc::Rc;
13 use std::result::Result;
14 use std::result::Result::Err;
15 use std::result::Result::Ok;
16 use std::string::String;
17 use std::vec::Vec;
18 
19 pub mod service;
20 pub mod target;
21 
22 use self::target::TargetUnit;
23 
24 //所有可解析的Unit都应该实现该trait
25 pub trait Unit {
26     /// @brief 从文件获取到Unit,该函数是解析Unit文件的入口函数
27     ///
28     /// 从path解析Unit属性
29     ///
30     /// @param path 需解析的文件
31     ///
32     /// @return 解析成功则返回对应Unit的Rc指针,否则返回Err
33     fn from_path(path: &str) -> Result<Rc<Self>, ParseError>
34     where
35         Self: Sized;
36 
37     fn as_any(&self) -> &dyn Any;
38 
39     /// @brief 设置Unit属性
40     ///
41     /// 设置对应Unit属性
42     ///
43     /// @param segment  属性段类型
44     ///
45     /// @param attr     属性名
46     ///
47     /// @param val      属性值
48     ///
49     /// @return 设置成功则返回Ok(()),否则返回Err
50     fn set_attr(&mut self, segment: Segment, attr: &str, val: &str) -> Result<(), ParseError>;
51 
52     /// # 设置每个Unit都应该有的属性
53     ///
54     /// 设置BaseUnit
55     ///
56     /// ## param unit_base  设置值
57     fn set_unit_base(&mut self, unit_base: BaseUnit);
58 
59     /// # 获取UnitType
60     ///
61     /// ## return UnitType
62     fn unit_type(&self) -> UnitType;
63 }
64 
65 //Unit状态
66 #[derive(Clone, Copy, Debug)]
67 enum UnitState {
68     Enabled,
69     Disabled,
70     Static,
71     Masked,
72 }
73 
74 //Unit类型
75 #[derive(Clone, Copy, PartialEq, Debug)]
76 pub enum UnitType {
77     Automount,
78     Device,
79     Mount,
80     Path,
81     Scope,
82     Service,
83     Slice,
84     Snapshot,
85     Socket,
86     Swap,
87     Target,
88     Timer,
89     Unknown,
90 }
91 
92 //记录unit文件基本信息,这个结构体里面的信息是所有Unit文件都可以有的属性
93 pub struct BaseUnit {
94     unit_part: UnitPart,
95     install_part: InstallPart,
96     state: UnitState,
97     unit_type: UnitType,
98 }
99 
100 impl Default for BaseUnit {
101     fn default() -> Self {
102         BaseUnit {
103             unit_part: UnitPart::default(),
104             install_part: InstallPart::default(),
105             state: UnitState::Disabled,
106             unit_type: UnitType::Unknown,
107         }
108     }
109 }
110 
111 impl BaseUnit {
112     pub fn set_state(&mut self, state: UnitState) {
113         self.state = state;
114     }
115 
116     pub fn set_unit_type(&mut self, utype: UnitType) {
117         self.unit_type = utype;
118     }
119 
120     pub fn set_unit_part_attr(
121         &mut self,
122         attr_type: &BaseUnitAttr,
123         val: &str,
124     ) -> Result<(), ParseError> {
125         return self.unit_part.set_attr(attr_type, val);
126     }
127 
128     pub fn set_install_part_attr(
129         &mut self,
130         attr_type: &InstallUnitAttr,
131         val: &str,
132     ) -> Result<(), ParseError> {
133         return self.install_part.set_attr(attr_type, val);
134     }
135 
136     pub fn parse_and_set_attribute(&self) -> Result<(), ParseError> {
137         return Ok(());
138     }
139 }
140 
141     pub fn unit_part(&self) -> &UnitPart {
142         &self.unit_part
143     }
144 
145     pub fn install_part(&self) -> &InstallPart {
146         &self.install_part
147     }
148 
149     pub fn state(&self) -> &UnitState {
150         &self.state
151     }
152 
153     pub fn unit_type(&self) -> &UnitType {
154         &self.unit_type
155     }
156 }
157 
158 #[derive(Default,Debug)]
159 pub struct Url {
160     pub url_string: String, // pub protocol: String,
161                             // pub host: String,
162                             // pub port: Option<u16>,
163                             // pub path: String,
164                             // pub query: Option<String>,
165                             // pub fragment: Option<String>,
166 }
167 
168 //对应Unit文件的Unit段
169 pub struct UnitPart {
170     description: String,
171     documentation: Vec<Url>,
172     requires: Vec<Rc<dyn Unit>>,
173     wants: Vec<Rc<dyn Unit>>,
174     after: Vec<Rc<dyn Unit>>,
175     before: Vec<Rc<dyn Unit>>,
176     binds_to: Vec<Rc<dyn Unit>>,
177     part_of: Vec<Rc<dyn Unit>>,
178     on_failure: Vec<Rc<dyn Unit>>,
179     conflicts: Vec<Rc<dyn Unit>>,
180 }
181 
182 impl Default for UnitPart {
183     fn default() -> Self {
184         UnitPart {
185             description: String::new(),
186             documentation: Vec::new(),
187             requires: Vec::new(),
188             wants: Vec::new(),
189             after: Vec::new(),
190             before: Vec::new(),
191             binds_to: Vec::new(),
192             part_of: Vec::new(),
193             on_failure: Vec::new(),
194             conflicts: Vec::new(),
195         }
196     }
197 }
198 
199 impl UnitPart {
200     pub fn set_attr(&mut self, attr: &BaseUnitAttr, val: &str) -> Result<(), ParseError> {
201         match attr {
202             BaseUnitAttr::None => {
203                 return Err(ParseError::new(ParseErrorType::ESyntaxError,String::new(),0));
204             }
205             BaseUnitAttr::Description => self.description = String::from(val),
206             BaseUnitAttr::Documentation => {
207                 self.documentation.extend(UnitParseUtil::parse_url(val)?)
208             }
209             BaseUnitAttr::Requires => {
210                 let units = val.split_whitespace().collect::<Vec<&str>>();
211                 //TODO:目前先加入requires列表,可能会出现循环依赖问题,后续应解决循环依赖问题
212                 for unit_path in units {
213                     self.requires
214                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
215                 }
216             }
217             BaseUnitAttr::Wants => {
218                 let units = val.split_whitespace().collect::<Vec<&str>>();
219                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
220                 for unit_path in units {
221                     self.wants
222                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
223                 }
224             }
225             BaseUnitAttr::After => {
226                 let units = val.split_whitespace().collect::<Vec<&str>>();
227                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
228                 for unit_path in units {
229                     self.after
230                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
231                 }
232             }
233             BaseUnitAttr::Before => {
234                 let units = val.split_whitespace().collect::<Vec<&str>>();
235                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
236                 for unit_path in units {
237                     self.before
238                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
239                 }
240             }
241             BaseUnitAttr::BindsTo => {
242                 let units = val.split_whitespace().collect::<Vec<&str>>();
243                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
244                 for unit_path in units {
245                     self.binds_to
246                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
247                 }
248             }
249             BaseUnitAttr::PartOf => {
250                 let units = val.split_whitespace().collect::<Vec<&str>>();
251                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
252                 for unit_path in units {
253                     self.part_of
254                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
255                 }
256             }
257             BaseUnitAttr::OnFailure => {
258                 let units = val.split_whitespace().collect::<Vec<&str>>();
259                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
260                 for unit_path in units {
261                     self.on_failure
262                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
263                 }
264             }
265             BaseUnitAttr::Conflicts => {
266                 let units = val.split_whitespace().collect::<Vec<&str>>();
267                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
268                 for unit_path in units {
269                     let unit = UnitParseUtil::parse_unit_no_type(unit_path)?;
270                     self.conflicts.push(unit);
271                 }
272             }
273         }
274         return Ok(());
275     }
276 
277     pub fn description(&self) -> &str {
278         &self.description
279     }
280 
281     pub fn documentation(&self) -> &[Url] {
282         &self.documentation
283     }
284 
285     pub fn requires(&self) -> &[Rc<dyn Unit>] {
286         &self.requires
287     }
288 
289     pub fn wants(&self) -> &[Rc<dyn Unit>] {
290         &self.wants
291     }
292 
293     pub fn after(&self) -> &[Rc<dyn Unit>] {
294         &self.after
295     }
296 
297     pub fn before(&self) -> &[Rc<dyn Unit>] {
298         &self.before
299     }
300 
301     pub fn binds_to(&self) -> &[Rc<dyn Unit>] {
302         &self.binds_to
303     }
304 
305     pub fn part_of(&self) -> &[Rc<dyn Unit>] {
306         &self.part_of
307     }
308 
309     pub fn on_failure(&self) -> &[Rc<dyn Unit>] {
310         &self.on_failure
311     }
312 
313     pub fn conflicts(&self) -> &[Rc<dyn Unit>] {
314         &self.conflicts
315     }
316 }
317 
318 //对应Unit文件的Install段
319 pub struct InstallPart {
320     wanted_by: Vec<Rc<TargetUnit>>,
321     requires_by: Vec<Rc<TargetUnit>>,
322     also: Vec<Rc<dyn Unit>>,
323     alias: String,
324 }
325 
326 impl Default for InstallPart {
327     fn default() -> Self {
328         InstallPart {
329             wanted_by: Vec::new(),
330             requires_by: Vec::new(),
331             also: Vec::new(),
332             alias: String::new(),
333         }
334     }
335 }
336 
337 impl InstallPart {
338     pub fn set_attr(&mut self, attr: &InstallUnitAttr, val: &str) -> Result<(), ParseError> {
339         match attr {
340             InstallUnitAttr::RequiredBy => {
341                 let units = val.split_whitespace().collect::<Vec<&str>>();
342                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
343                 for unit_path in units {
344                     let unit = UnitParseUtil::parse_unit::<TargetUnit>(unit_path)?;
345                     self.requires_by.push(unit);
346                 }
347             }
348             InstallUnitAttr::Also => {
349                 let units = val.split_whitespace().collect::<Vec<&str>>();
350                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
351                 for unit_path in units {
352                     let unit = UnitParseUtil::parse_unit_no_type(unit_path)?;
353                     self.also.push(unit);
354                 }
355             }
356             InstallUnitAttr::WantedBy => {
357                 let units = val.split_whitespace().collect::<Vec<&str>>();
358                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
359                 for unit_path in units {
360                     let unit = UnitParseUtil::parse_unit::<TargetUnit>(unit_path)?;
361                     self.wanted_by.push(unit);
362                 }
363             }
364             InstallUnitAttr::Alias => {
365                 self.alias = String::from(val);
366             }
367             InstallUnitAttr::None => {
368                 return Err(ParseError::new(ParseErrorType::EINVAL,String::new(),0));
369             }
370         }
371         return Ok(());
372     }
373 
374     pub fn wanted_by(&self) -> &[Rc<TargetUnit>] {
375         &self.wanted_by
376     }
377 
378     pub fn requires_by(&self) -> &[Rc<TargetUnit>] {
379         &self.requires_by
380     }
381 
382     pub fn also(&self) -> &[Rc<dyn Unit>] {
383         &self.also
384     }
385 
386     pub fn alias(&self) -> &str {
387         &self.alias
388     }
389 }
390 //对应Unit文件的各种属性
391 pub enum BaseUnitAttr {
392     None,
393 
394     //Unit段
395     //描述该Unit文件的信息
396     Description,
397     //指定服务文档
398     Documentation,
399     //依赖的其它 Unit 列表
400     Requires,
401     //这个 Unit 启动时,触发启动列出的每个 Unit 模块,而不去考虑这些模板启动是否成功
402     Wants,
403     //后面列出的所有模块全部启动完成以后,才会启动当前的服务
404     After,
405     //在启动指定的任务一个模块之间,都会首先确证当前服务已经运行
406     Before,
407     //这些Unit启动失败时该任务失败,都成功时该任务成功,在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启
408     BindsTo,
409     //仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动
410     PartOf,
411     //当这个模板启动失败时,就会自动启动列出的每个模块
412     OnFailure,
413     //与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然
414     Conflicts,
415 }
416 
417 pub enum InstallUnitAttr {
418     None,
419     //Install段
420     //依赖当前服务的模块。当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .wants 后缀构成的子目录中
421     WantedBy,
422     //依赖当前服务的模块。当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .required 后缀构成的子目录中
423     RequiredBy,
424     //当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit
425     Also,
426     //别名
427     Alias,
428 }
429