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