diff options
author | Rina Fujino <18257209+rina23q@users.noreply.github.com> | 2022-01-10 17:57:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-10 17:57:41 +0100 |
commit | 3ab4cf779ebacafd5990285d07ccfe03bebaea03 (patch) | |
tree | ae8f06bc774a39f2575abf933cb92a04fc710a79 /crates/core/tedge/src/system_services/managers/systemd.rs | |
parent | 9c4dee566f25a7a3a2b2548a03d0c4a4bf65b66e (diff) |
#639 Remove the dependency on systemd (#729)
* The purpose of this change is to get rid of the hard-coded dependencies on systemd from tedge connect/disconnect, to allow users to use other system managers, e.g. OpenRC, initd, etc..
* If /etc/tedge/system.toml exists, tedge connect/disconnect uses the service manager defined in the file.
* If the file is not given by user, tedge connect/disconnect uses /bin/systemctl as the service manager. (the same behaviour as we have it so far)
* Delete old service implementation files for BSD, OpenRC, systemd, and NULL.
* Add system.toml example files for BSD and OpenRC.
* Add a reference guide to explain the format of system.toml configuration file.
Signed-off-by: Rina Fujino <18257209+rina23q@users.noreply.github.com>
Diffstat (limited to 'crates/core/tedge/src/system_services/managers/systemd.rs')
-rw-r--r-- | crates/core/tedge/src/system_services/managers/systemd.rs | 217 |
1 files changed, 0 insertions, 217 deletions
diff --git a/crates/core/tedge/src/system_services/managers/systemd.rs b/crates/core/tedge/src/system_services/managers/systemd.rs deleted file mode 100644 index e5107b77..00000000 --- a/crates/core/tedge/src/system_services/managers/systemd.rs +++ /dev/null @@ -1,217 +0,0 @@ -use crate::system_services::*; -use std::process::ExitStatus; -use tedge_users::*; - -#[derive(Debug)] -pub struct SystemdServiceManager { - systemctl_bin: String, - user_manager: UserManager, -} - -type ExitCode = i32; -type Error = SystemServiceError; - -const SYSTEMCTL_OK: ExitCode = 0; -const SYSTEMCTL_ERROR_GENERIC: ExitCode = 1; -const SYSTEMCTL_ERROR_UNIT_IS_NOT_ACTIVE: ExitCode = 3; -const SYSTEMCTL_ERROR_SERVICE_NOT_FOUND: ExitCode = 5; -const SYSTEMCTL_ERROR_SERVICE_NOT_LOADED: ExitCode = 5; - -const SYSTEMCTL_BIN: &str = "systemctl"; - -impl SystemdServiceManager { - pub fn new(user_manager: UserManager) -> Self { - Self { - systemctl_bin: SYSTEMCTL_BIN.into(), - user_manager, - } - } -} - -impl SystemServiceManager for SystemdServiceManager { - fn name(&self) -> &str { - "systemd" - } - - fn check_operational(&self) -> Result<(), SystemServiceError> { - match std::process::Command::new(&self.systemctl_bin) - .arg(SystemCtlParam::Version.as_str()) - .stdout(std::process::Stdio::null()) - .stderr(std::process::Stdio::null()) - .status() - { - Ok(status) if status.success() => Ok(()), - _ => Err(SystemServiceError::ServiceManagerUnavailable( - self.name().to_string(), - )), - } - } - - fn stop_service(&self, service: SystemService) -> Result<(), Error> { - let service_name = SystemService::as_service_name(service); - match self.call_systemd_subcmd_sudo(SystemCtlCmd::Stop, service_name)? { - SYSTEMCTL_OK => Ok(()), - SYSTEMCTL_ERROR_GENERIC => Err(SystemdError::UnspecificError { - service: service_name, - cmd: SystemCtlCmd::Stop.as_str(), - hint: "Lacking permissions.", - } - .into()), - SYSTEMCTL_ERROR_SERVICE_NOT_LOADED => Err(SystemdError::ServiceNotLoaded { - service: service_name, - } - .into()), - code => Err(SystemdError::UnhandledReturnCode { code }.into()), - } - } - - // Note that restarting a unit with this command does not necessarily flush out all of the unit's resources before it is started again. - // For example, the per-service file descriptor storage facility (see FileDescriptorStoreMax= in systemd.service(5)) will remain intact - // as long as the unit has a job pending, and is only cleared when the unit is fully stopped and no jobs are pending anymore. - // If it is intended that the file descriptor store is flushed out, too, during a restart operation an explicit - // systemctl stop command followed by systemctl start should be issued. - fn restart_service(&self, service: SystemService) -> Result<(), Error> { - let service_name = SystemService::as_service_name(service); - match self.call_systemd_subcmd_sudo(SystemCtlCmd::Restart, service_name)? { - SYSTEMCTL_OK => Ok(()), - SYSTEMCTL_ERROR_GENERIC => Err(SystemdError::UnspecificError { - service: service_name, - cmd: SystemCtlCmd::Restart.as_str(), - hint: "Lacking permissions or service's process exited with error code.", - } - .into()), - SYSTEMCTL_ERROR_SERVICE_NOT_FOUND => Err(SystemdError::ServiceNotFound { - service: service_name, - } - .into()), - code => Err(SystemdError::UnhandledReturnCode { code }.into()), - } - } - - fn enable_service(&self, service: SystemService) -> Result<(), Error> { - let service_name = SystemService::as_service_name(service); - match self.call_systemd_subcmd_sudo(SystemCtlCmd::Enable, service_name)? { - SYSTEMCTL_OK => Ok(()), - SYSTEMCTL_ERROR_GENERIC => Err(SystemdError::UnspecificError { - service: service_name, - cmd: SystemCtlCmd::Enable.as_str(), - hint: "Lacking permissions.", - } - .into()), - code => Err(SystemdError::UnhandledReturnCode { code }.into()), - } - } - - fn disable_service(&self, service: SystemService) -> Result<(), Error> { - let service_name = SystemService::as_service_name(service); - match self.call_systemd_subcmd_sudo(SystemCtlCmd::Disable, service_name)? { - SYSTEMCTL_OK => Ok(()), - SYSTEMCTL_ERROR_GENERIC => Err(SystemdError::UnspecificError { - service: service_name, - cmd: SystemCtlCmd::Disable.as_str(), - hint: "Lacking permissions.", - } - .into()), - code => Err(SystemdError::UnhandledReturnCode { code }.into()), - } - } - - fn is_service_running(&self, service: SystemService) -> Result<bool, Error> { - let service_name = SystemService::as_service_name(service); - match self.call_systemd_subcmd(SystemCtlCmd::IsActive, service_name)? { - SYSTEMCTL_OK => Ok(true), - SYSTEMCTL_ERROR_UNIT_IS_NOT_ACTIVE => Ok(false), - code => Err(SystemdError::UnhandledReturnCode { code }.into()), - } - } -} - -impl SystemdServiceManager { - fn call_systemd_subcmd_sudo( - &self, - systemctl_subcmd: SystemCtlCmd, - arg: &str, - ) -> Result<i32, Error> { - let _root_guard = self.user_manager.become_user(ROOT_USER); - self.call_systemd_subcmd(systemctl_subcmd, arg) - } - - fn call_systemd_subcmd(&self, systemctl_subcmd: SystemCtlCmd, arg: &str) -> Result<i32, Error> { - cmd_nullstdio_args_with_code(&self.systemctl_bin, &[systemctl_subcmd.as_str(), arg])? - .code() - .ok_or(Error::UnexpectedExitStatus) - } -} - -fn cmd_nullstdio_args_with_code(command: &str, args: &[&str]) -> Result<ExitStatus, Error> { - Ok(std::process::Command::new(command) - .args(args) - .stdout(std::process::Stdio::null()) - .stderr(std::process::Stdio::null()) - .status()?) -} - -#[derive(Debug)] -enum SystemCtlCmd { - Enable, - Disable, - IsActive, - Stop, - Restart, -} - -impl SystemCtlCmd { - fn as_str(&self) -> &'static str { - match self { - SystemCtlCmd::Enable => "enable", - SystemCtlCmd::Disable => "disable", - SystemCtlCmd::IsActive => "is-active", - SystemCtlCmd::Stop => "stop", - SystemCtlCmd::Restart => "restart", - } - } -} - -impl From<SystemCtlCmd> for String { - fn from(val: SystemCtlCmd) -> Self { - val.as_str().into() - } -} - -#[derive(Debug)] -enum SystemCtlParam { - Version, -} - -impl SystemCtlParam { - fn as_str(&self) -> &'static str { - match self { - SystemCtlParam::Version => "--version", - } - } -} - -impl From<SystemCtlParam> for String { - fn from(val: SystemCtlParam) -> Self { - val.as_str().into() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn cmd_nullstdio_args_expected_exit_code_zero() { - // There is a chance that this may fail on very embedded system which will not have 'ls' command on busybox. - assert_eq!( - cmd_nullstdio_args_with_code("ls", &[]).unwrap().code(), - Some(0) - ); - } - - #[test] - fn cmd_nullstdio_args_command_not_exists() { - assert!(cmd_nullstdio_args_with_code("test-command", &[]).is_err()) - } -} |