sysd_manager_comcontroler/sysdbus/
to_proxy.rs1#![allow(dead_code)]
2
3use std::sync::OnceLock;
4
5use base::{
6 consts::{MAX_HEART_BEAT_ELAPSE, MIN_HEART_BEAT_ELAPSE},
7 enums::UnitDBusLevel,
8 proxy::{DisEnAbleUnitFiles, DisEnAbleUnitFilesResponse},
9};
10use futures_util::stream::StreamExt;
11use tokio::{
12 task::JoinHandle,
13 time::{self, Duration},
14};
15use tracing::{debug, info, warn};
16use zbus::proxy;
17use zvariant::OwnedObjectPath;
18
19use crate::{
20 errors::SystemdErrors,
21 sysdbus::{get_blocking_connection, get_connection, run_context},
22};
23
24#[proxy(
25 interface = "io.github.plrigaux.SysDManager",
26 default_service = "io.github.plrigaux.SysDManager",
27 default_path = "/io/github/plrigaux/SysDManager"
28)]
29pub trait SysDManagerComLink {
30 fn start_unit(&self, unit_name: &str, mode: &str) -> zbus::fdo::Result<OwnedObjectPath>;
31 fn stop_unit(&self, unit_name: &str, mode: &str) -> zbus::fdo::Result<OwnedObjectPath>;
32 fn restart_unit(&self, unit_name: &str, mode: &str) -> zbus::fdo::Result<OwnedObjectPath>;
33 fn reload_unit(&self, unit_name: &str, mode: &str) -> zbus::fdo::Result<OwnedObjectPath>;
34 fn clean_unit(&self, unit_name: &str, what: &[&str]) -> zbus::Result<()>;
35 fn freeze_unit(&self, unit_name: &str) -> zbus::fdo::Result<()>;
36 fn thaw_unit(&self, unit_name: &str) -> zbus::fdo::Result<()>;
37 fn reload(&self) -> zbus::fdo::Result<()>;
38
39 fn create_drop_in(
40 &mut self,
41 runtime: bool,
42 unit_name: &str,
43 file_name: &str,
44 content: &str,
45 ) -> zbus::fdo::Result<()>;
46 fn save_file(&mut self, file_name: &str, content: &str) -> zbus::fdo::Result<u64>;
47
48 fn revert_unit_files(&self, file_names: &[&str]) -> zbus::fdo::Result<Vec<DisEnAbleUnitFiles>>;
49
50 fn enable_unit_files_with_flags(
51 &mut self,
52 files: &[&str],
53 flags: u64,
54 ) -> zbus::fdo::Result<DisEnAbleUnitFilesResponse>;
55
56 fn disable_unit_files_with_flags(
57 &mut self,
58 files: &[&str],
59 flags: u64,
60 ) -> zbus::fdo::Result<DisEnAbleUnitFilesResponse>;
61
62 #[zbus(signal)]
63 fn hello(msg: String) -> zbus::fdo::Result<()>;
64
65 fn heart_beat(&self) -> zbus::fdo::Result<u64>;
66}
67
68fn ensure_proxy_up() {
72 }
74
75fn get_proxy<'a>() -> Result<SysDManagerComLinkProxyBlocking<'a>, SystemdErrors> {
76 let destination = run_context().destination_address();
77 let connection = get_blocking_connection(UnitDBusLevel::System)?;
78
79 info!("BusName Destination {}", destination);
80 let proxy = SysDManagerComLinkProxyBlocking::builder(&connection)
81 .destination(destination)?
83 .build()?;
84
85 Ok(proxy)
86}
87
88pub(crate) async fn get_proxy_async<'a>() -> Result<SysDManagerComLinkProxy<'a>, SystemdErrors> {
89 let destination = super::RUN_CONTEXT
90 .get()
91 .expect("Supposed to be init")
92 .destination_address();
93 let connection = get_connection(UnitDBusLevel::System).await?;
94
95 info!("BusName Destination {}", destination);
96 let proxy = SysDManagerComLinkProxy::builder(&connection)
97 .destination(destination)?
99 .build()
100 .await?;
101
102 Ok(proxy)
103}
104
105pub fn start_unit(unit_name: &str, mode: &str) -> Result<String, SystemdErrors> {
106 let proxy = get_proxy()?;
107
108 let s = proxy.start_unit(unit_name, mode)?;
109 Ok(s.to_string())
110}
111
112pub fn stop_unit(unit_name: &str, mode: &str) -> Result<String, SystemdErrors> {
113 let proxy = get_proxy()?;
114
115 let s = proxy.stop_unit(unit_name, mode)?;
116 Ok(s.to_string())
117}
118
119pub fn restart_unit(unit_name: &str, mode: &str) -> Result<String, SystemdErrors> {
120 let proxy = get_proxy()?;
121
122 let s = proxy.restart_unit(unit_name, mode)?;
123 Ok(s.to_string())
124}
125
126pub fn clean_unit(unit_name: &str, what: &[&str]) -> Result<(), SystemdErrors> {
127 let proxy = get_proxy()?;
128
129 proxy.clean_unit(unit_name, what)?;
130 Ok(())
131}
132
133pub fn freeze_unit(unit_name: &str) -> Result<(), SystemdErrors> {
134 let proxy = get_proxy()?;
135 proxy.freeze_unit(unit_name)?;
136 Ok(())
137}
138
139pub fn thaw_unit(unit_name: &str) -> Result<(), SystemdErrors> {
140 let proxy: SysDManagerComLinkProxyBlocking<'_> = get_proxy()?;
141 proxy.thaw_unit(unit_name)?;
142 Ok(())
143}
144
145pub async fn reload() -> Result<(), SystemdErrors> {
146 let proxy = get_proxy_async().await?;
147 proxy.reload().await?;
148 Ok(())
149}
150
151fn extract_job_id(job: &str) -> Option<u32> {
152 job.rsplit_once('/')
153 .and_then(|(_, id)| id.parse::<u32>().ok())
154}
155
156pub async fn lazy_start_proxy_async() -> Result<(), SystemdErrors> {
157 crate::sysdbus::init_proxy_async2().await?;
158
159 Ok(())
160}
161
162pub(crate) async fn wait_hello(mut hello_stream: HelloStream) -> Result<(), SystemdErrors> {
163 if let Some(msg) = hello_stream.next().await {
164 let args = msg.args()?;
165 info!("Hello Proxy Args {:?}", args);
166 }
167 Ok(())
168}
169
170pub fn lazy_start_proxy_block() -> Result<(), SystemdErrors> {
171 crate::runtime().block_on(async move {
172 warn!("lazy 1");
173 lazy_start_proxy_async().await;
174 warn!("lazy 2");
175 });
176 Ok(())
177}
178
179static HEART_BEAT_HANDLE: OnceLock<JoinHandle<Result<(), SystemdErrors>>> = OnceLock::new();
180pub(crate) fn start_heart_beat() {
181 if let Some(join_handle) = HEART_BEAT_HANDLE.get()
182 && !join_handle.is_finished()
183 {
184 warn!("There is already an heart beat thread running");
185 } else {
186 info!("Starting Heart Beat");
187 let handle = tokio::spawn(send_heart_beat());
188 HEART_BEAT_HANDLE.set(handle);
189 }
190}
191
192async fn send_heart_beat() -> Result<(), SystemdErrors> {
193 let proxy = get_proxy_async().await?;
194 loop {
195 match proxy.heart_beat().await {
196 Ok(delay) => {
197 debug!("Heath Beat delay {delay} millis");
198 let delay = delay.clamp(MIN_HEART_BEAT_ELAPSE, MAX_HEART_BEAT_ELAPSE);
199 time::sleep(Duration::from_millis(delay)).await;
200 }
201 Err(err) => {
202 warn!("Send Heart Beat Error: {err:?}");
203 return Err(err.into());
204 }
205 }
206 }
207}
208
209#[macro_export]
210macro_rules! proxy_call_blocking {
211 ($func:ident, $($param:expr),+) => {
212 match $crate::to_proxy::$func($($param),+) {
213 Ok(ok) => Ok(ok),
214 Err(SystemdErrors::ZFdoServiceUnknowm(msg)) => {
215 warn!("Blocking ServiceUnkown: {:?} Func: {}", msg, stringify!($func));
216 $crate::to_proxy::lazy_start_proxy_block();
217 $crate::to_proxy::$func($($param),+)
218 },
219 Err(err) => Err(err)
220 }
221 }
222}
223
224#[macro_export]
225macro_rules! proxy_call_async {
226 ($func:ident) => {
227 proxy_call_async!($func,)
228 };
229
230 ($func:ident, $($param:expr),*) => {
231 match $crate::to_proxy::$func($($param),*).await {
232 Ok(ok) => Ok(ok),
233 Err(SystemdErrors::ZFdoServiceUnknowm(msg)) => {
234 warn!("Async ServiceUnkown: {:?} Function: {}", msg, stringify!($func));
235 $crate::to_proxy::lazy_start_proxy_async().await;
236 $crate::to_proxy::$func($($param),*).await
237 },
238 Err(err) => Err(err)
239 }
240 }
241}
242
243pub(crate) async fn create_drop_in(
244 runtime: bool,
245 unit_name: &str,
246 file_path: &str,
247 content: &str,
248) -> Result<(), SystemdErrors> {
249 let mut proxy = get_proxy_async().await?;
250 proxy
251 .create_drop_in(runtime, unit_name, file_path, content)
252 .await
253 .map_err(|e| e.into())
254}
255
256pub async fn save_file(file_path: &str, content: &str) -> Result<u64, SystemdErrors> {
257 let mut proxy = get_proxy_async().await?;
258 proxy
259 .save_file(file_path, content)
260 .await
261 .map_err(|e| e.into())
262}
263
264pub async fn revert_unit_files(
265 unit_names: &[&str],
266) -> Result<Vec<DisEnAbleUnitFiles>, SystemdErrors> {
267 let proxy = get_proxy_async().await?;
268 proxy
269 .revert_unit_files(unit_names)
270 .await
271 .map_err(|e| e.into())
272}
273
274pub fn enable_unit_files_with_flags(
275 unit_files: &[&str],
276 flags: u64,
277) -> Result<DisEnAbleUnitFilesResponse, SystemdErrors> {
278 let mut proxy: SysDManagerComLinkProxyBlocking<'_> = get_proxy()?;
279 proxy
280 .enable_unit_files_with_flags(unit_files, flags)
281 .map_err(|err| err.into())
282}
283
284pub fn disable_unit_files_with_flags(
285 unit_files: &[&str],
286 flags: u64,
287) -> Result<DisEnAbleUnitFilesResponse, SystemdErrors> {
288 let mut proxy: SysDManagerComLinkProxyBlocking<'_> = get_proxy()?;
289 proxy
290 .disable_unit_files_with_flags(unit_files, flags)
291 .map_err(|err| err.into())
292}