Skip to content
This repository was archived by the owner on Dec 21, 2021. It is now read-only.

Commit 0c826f8

Browse files
Synchronize pod state with systemd service state (#164)
* Functions to start and stop systemd units now await the JobRemoved signal * All dependencies upgraded * Changelog converted to asciidoc * Version set to 0.2.0 and changelog updated
1 parent eb68eb0 commit 0c826f8

File tree

6 files changed

+371
-125
lines changed

6 files changed

+371
-125
lines changed

CHANGELOG.adoc

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
= Changelog
2+
3+
== 0.2.0 - 2021-05-20
4+
5+
:159: https://github.com/stackabletech/agent/pull/159[#159]
6+
:164: https://github.com/stackabletech/agent/pull/164[#164]
7+
8+
=== Added
9+
* Templating facility added to the `config-directory` parameter ({159}).
10+
11+
=== Fixed
12+
* Pod state synchronized with systemd service state ({164}).
13+
14+
== 0.1.0 - 2021-05-17
15+
16+
:1: https://github.com/stackabletech/agent/pull/1[#1]
17+
:18: https://github.com/stackabletech/agent/pull/18[#18]
18+
:23: https://github.com/stackabletech/agent/pull/23[#23]
19+
:25: https://github.com/stackabletech/agent/pull/25[#25]
20+
:26: https://github.com/stackabletech/agent/pull/26[#26]
21+
:30: https://github.com/stackabletech/agent/pull/30[#30]
22+
:32: https://github.com/stackabletech/agent/pull/32[#32]
23+
:35: https://github.com/stackabletech/agent/pull/35[#35]
24+
:36: https://github.com/stackabletech/agent/pull/36[#36]
25+
:40: https://github.com/stackabletech/agent/pull/40[#40]
26+
:43: https://github.com/stackabletech/agent/pull/43[#43]
27+
:50: https://github.com/stackabletech/agent/pull/50[#50]
28+
:53: https://github.com/stackabletech/agent/pull/53[#53]
29+
:56: https://github.com/stackabletech/agent/pull/56[#56]
30+
:57: https://github.com/stackabletech/agent/pull/57[#57]
31+
:63: https://github.com/stackabletech/agent/pull/63[#63]
32+
:72: https://github.com/stackabletech/agent/pull/72[#72]
33+
:73: https://github.com/stackabletech/agent/pull/73[#73]
34+
:77: https://github.com/stackabletech/agent/pull/77[#77]
35+
:78: https://github.com/stackabletech/agent/pull/78[#78]
36+
:79: https://github.com/stackabletech/agent/pull/79[#79]
37+
:94: https://github.com/stackabletech/agent/pull/94[#94]
38+
:100: https://github.com/stackabletech/agent/pull/100[#100]
39+
:109: https://github.com/stackabletech/agent/pull/109[#109]
40+
:110: https://github.com/stackabletech/agent/pull/110[#110]
41+
:135: https://github.com/stackabletech/agent/pull/135[#135]
42+
:138: https://github.com/stackabletech/agent/pull/138[#138]
43+
:144: https://github.com/stackabletech/agent/pull/144[#144]
44+
:145: https://github.com/stackabletech/agent/pull/145[#145]
45+
:152: https://github.com/stackabletech/agent/pull/152[#152]
46+
47+
=== Added
48+
* Apache license v2.0 set ({23}).
49+
* Krustlet based agent implementation created ({1}, {18}, {26}, {35}, {40}).
50+
* Functionality to stop and restart processes added ({25}).
51+
* Agent restart without impacting running services enabled ({63}).
52+
* Rendering of template variables to environment variables added ({30}).
53+
* Setting of pod condition "ready" for state "running" added ({32}).
54+
* Support for command line parameters added ({36}, {50}, {72}, {109}).
55+
* Integration with systemd implemented ({43}, {53}, {100}, {152}).
56+
* Dependabot and security audit enabled ({56}, {57}).
57+
* Building and publishing of nightly deb and rpm packages added ({73}, {78}, {94}, {110}, {144}).
58+
* Bootstrapping of certificates and kubeconfig added ({77}).
59+
* Support for running of services as application users added ({79}).
60+
* Retrieval of container logs with kubectl logs implemented ({135}).
61+
* Configuration of terminationGracePeriodSeconds considered in systemd units ({138}).
62+
* Systemd dependency adapted so that it is compatible with systemd version 241 ({145}).

CHANGELOG.md

Lines changed: 0 additions & 20 deletions
This file was deleted.

Cargo.lock

Lines changed: 25 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "stackable-agent"
33
description = "The component of the Stackable Platform that manages installation of services on the workers"
4-
version = "0.2.0-nightly"
4+
version = "0.2.0"
55
authors = ["Sönke Liebau <[email protected]>"]
66
edition = "2018"
77
license = "Apache-2.0"
@@ -15,6 +15,7 @@ async-trait = "0.1"
1515
byteorder = "1.4"
1616
env_logger = "0.8"
1717
flate2 = "1.0"
18+
futures-util = "0.3"
1819
handlebars = "3.5"
1920
hostname = "0.3"
2021
k8s-openapi = { version = "0.11", default-features = false, features = ["api", "v1_18"] }

src/provider/systemdmanager/manager.rs

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@
33
//! The module offers the ability to create, remove, start, stop, enable and
44
//! disable systemd units.
55
//!
6-
use super::systemd1_api::{ActiveState, AsyncManagerProxy, StartMode, StopMode};
6+
use super::systemd1_api::{
7+
ActiveState, AsyncJobProxy, AsyncManagerProxy, JobRemovedResult, JobRemovedSignal,
8+
ManagerSignals, StartMode, StopMode,
9+
};
710
use crate::provider::systemdmanager::systemdunit::SystemDUnit;
811
use crate::provider::StackableError;
912
use crate::provider::StackableError::RuntimeError;
1013
use anyhow::anyhow;
14+
use futures_util::{future, stream::StreamExt};
1115
use log::debug;
1216
use std::fs;
1317
use std::fs::File;
18+
use std::future::Future;
1419
use std::io::Write;
1520
use std::path::PathBuf;
1621
use zbus::azync::Connection;
@@ -273,15 +278,17 @@ impl SystemdManager {
273278
/// systemd at the time this is called.
274279
/// To make a service known please take a look at the [`SystemdManager::enable`] function.
275280
pub async fn start(&self, unit: &str) -> anyhow::Result<()> {
276-
debug!("Attempting to start unit {}", unit);
281+
debug!("Trying to start unit [{}]", unit);
277282

278-
match self.proxy.start_unit(unit, StartMode::Fail).await {
279-
Ok(result) => {
280-
debug!("Successfully started service [{}]: [{:?}]", unit, result);
281-
Ok(())
282-
}
283-
Err(e) => Err(anyhow!("Error starting service [{}]: {}", unit, e)),
283+
let result = self
284+
.call_method(|proxy| proxy.start_unit(unit, StartMode::Fail))
285+
.await;
286+
287+
if result.is_ok() {
288+
debug!("Successfully started service [{}]", unit);
284289
}
290+
291+
result.map_err(|e| anyhow!("Error starting service [{}]: {}", unit, e))
285292
}
286293

287294
/// Attempts to stop a systemd unit
@@ -291,12 +298,62 @@ impl SystemdManager {
291298
pub async fn stop(&self, unit: &str) -> anyhow::Result<()> {
292299
debug!("Trying to stop systemd unit [{}]", unit);
293300

294-
match self.proxy.stop_unit(unit, StopMode::Fail).await {
295-
Ok(result) => {
296-
debug!("Successfully stopped service [{}]: [{:?}]", unit, result);
297-
Ok(())
298-
}
299-
Err(e) => Err(anyhow!("Error stopping service [{}]: {}", unit, e)),
301+
let result = self
302+
.call_method(|proxy| proxy.stop_unit(unit, StopMode::Fail))
303+
.await;
304+
305+
if result.is_ok() {
306+
debug!("Successfully stopped service [{}]", unit);
307+
}
308+
309+
result.map_err(|e| anyhow!("Error stopping service [{}]: {}", unit, e))
310+
}
311+
312+
/// Calls a systemd method and waits until the dependent job is
313+
/// finished.
314+
///
315+
/// The given method enqueues a job in systemd and returns the job
316+
/// object. Systemd sends out a `JobRemoved` signal when the job is
317+
/// dequeued. The signal contains the reason for the dequeuing like
318+
/// `"done"`, `"failed"`, or `"canceled"`.
319+
///
320+
/// This function subscribes to `JobRemoved` signals, calls the
321+
/// given method, awaits the signal for the corresponding job, and
322+
/// returns `Ok(())` if the result is [`JobRemovedResult::Done`].
323+
/// If the signal contains another result or no signal is returned
324+
/// (which should never happen) then an error with a corresponding
325+
/// message is returned.
326+
async fn call_method<'a, F, Fut>(&'a self, method: F) -> anyhow::Result<()>
327+
where
328+
F: Fn(&'a AsyncManagerProxy) -> Fut,
329+
Fut: Future<Output = zbus::Result<AsyncJobProxy<'a>>>,
330+
{
331+
let signals = self
332+
.proxy
333+
.receive_signal(ManagerSignals::JobRemoved.into())
334+
.await?
335+
.map(|message| message.body::<JobRemovedSignal>().unwrap());
336+
337+
let job = method(&self.proxy).await?;
338+
339+
let mut signals = signals
340+
.filter(|signal| future::ready(&signal.job.to_owned().into_inner() == job.path()));
341+
342+
let signal = signals.next().await;
343+
344+
// Unsubscribe from receiving signals.
345+
// If `signals` goes out of scope prematurely due to an error
346+
// then the subscription is cancelled synchronously in the
347+
// destructor of `SignalStream`.
348+
let _ = signals.into_inner().into_inner().close().await;
349+
350+
match signal {
351+
Some(message) if message.result == JobRemovedResult::Done => Ok(()),
352+
Some(message) => Err(anyhow!("The systemd job failed: {:?}", message)),
353+
None => Err(anyhow!(
354+
"No signal was returned for the systemd job: {:?}",
355+
job
356+
)),
300357
}
301358
}
302359

0 commit comments

Comments
 (0)