Skip to content

Commit f8bb62b

Browse files
committed
dbus: rauc: remove tacd-based update polling
Signed-off-by: Leonard Göhrs <l.goehrs@pengutronix.de>
1 parent 53d6d98 commit f8bb62b

File tree

3 files changed

+3
-290
lines changed

3 files changed

+3
-290
lines changed

src/broker/topic.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,6 @@ impl<E: Serialize + DeserializeOwned + Clone + PartialEq> Topic<E> {
336336

337337
self.modify(|prev| if prev != msg { msg } else { None });
338338
}
339-
340-
/// Wait until the topic is set to the specified value
341-
pub async fn wait_for(self: &Arc<Self>, val: E) {
342-
let (mut stream, sub) = self.clone().subscribe_unbounded();
343-
344-
// Unwrap here to keep the interface simple. The stream could only yield
345-
// None if the sender side is dropped, which will not happen as we hold
346-
// an Arc to self which contains the senders vec.
347-
while stream.next().await.unwrap() != val {}
348-
349-
sub.unsubscribe()
350-
}
351339
}
352340

353341
impl<E: Serialize + DeserializeOwned + Clone + Not + Not<Output = E>> Topic<E> {

src/dbus/rauc.rs

Lines changed: 3 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,12 @@
1515
// with this program; if not, write to the Free Software Foundation, Inc.,
1616
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1717

18-
use std::cmp::Ordering;
1918
use std::collections::HashMap;
20-
use std::time::{Duration, Instant};
2119

2220
use anyhow::Result;
2321
use async_std::channel::Receiver;
2422
use async_std::stream::StreamExt;
2523
use async_std::sync::Arc;
26-
use async_std::task::{sleep, spawn, JoinHandle};
2724
use log::warn;
2825
use serde::{Deserialize, Serialize};
2926

@@ -48,38 +45,6 @@ use installer::InstallerProxy;
4845

4946
#[cfg(feature = "demo_mode")]
5047
mod imports {
51-
use std::collections::HashMap;
52-
53-
pub(super) struct InstallerProxy<'a> {
54-
_dummy: &'a (),
55-
}
56-
57-
impl<'a> InstallerProxy<'a> {
58-
pub async fn new<C>(_conn: C) -> Option<InstallerProxy<'a>> {
59-
Some(Self { _dummy: &() })
60-
}
61-
62-
pub async fn inspect_bundle(
63-
&self,
64-
_source: &str,
65-
_args: HashMap<&str, zbus::zvariant::Value<'_>>,
66-
) -> zbus::Result<HashMap<String, zbus::zvariant::OwnedValue>> {
67-
let update: HashMap<String, String> = [
68-
(
69-
"compatible".into(),
70-
"Linux Automation GmbH - LXA TAC".into(),
71-
),
72-
("version".into(), "24.04-20240415070800".into()),
73-
]
74-
.into();
75-
76-
let info: HashMap<String, zbus::zvariant::OwnedValue> =
77-
[("update".into(), update.into())].into();
78-
79-
Ok(info)
80-
}
81-
}
82-
8348
pub(super) const CHANNELS_DIR: &str = "demo_files/usr/share/tacd/update_channels";
8449
}
8550

@@ -91,10 +56,6 @@ mod imports {
9156
pub(super) const CHANNELS_DIR: &str = "/usr/share/tacd/update_channels";
9257
}
9358

94-
const RELOAD_RATE_LIMIT: Duration = Duration::from_secs(10 * 60);
95-
const RETRY_INTERVAL_MIN: Duration = Duration::from_secs(60);
96-
const RETRY_INTERVAL_MAX: Duration = Duration::from_secs(60 * 60);
97-
9859
use imports::*;
9960

10061
#[derive(Serialize, Deserialize, Clone)]
@@ -158,20 +119,10 @@ pub struct Rauc {
158119
pub channels: Arc<Topic<Channels>>,
159120
pub reload: Arc<Topic<bool>>,
160121
pub should_reboot: Arc<Topic<bool>>,
122+
#[allow(dead_code)]
161123
pub enable_polling: Arc<Topic<bool>>,
162124
}
163125

164-
fn compare_versions(v1: &str, v2: &str) -> Option<Ordering> {
165-
// Version strings look something like this: "4.0-0-20230428214619"
166-
// Use string sorting on the date part to determine which bundle is newer.
167-
let date_1 = v1.rsplit_once('-').map(|(_, d)| d);
168-
let date_2 = v2.rsplit_once('-').map(|(_, d)| d);
169-
170-
// Return Sone if either version could not be split or a Some with the
171-
// ordering between the dates.
172-
date_1.zip(date_2).map(|(d1, d2)| d1.cmp(d2))
173-
}
174-
175126
#[cfg(not(feature = "demo_mode"))]
176127
fn would_reboot_into_other_slot(slot_status: &SlotStatus, primary: Option<String>) -> Result<bool> {
177128
let rootfs_0 = slot_status.get("rootfs_0");
@@ -231,97 +182,15 @@ fn would_reboot_into_other_slot(slot_status: &SlotStatus, primary: Option<String
231182
}
232183
}
233184

234-
async fn channel_polling_task(
235-
conn: Arc<Connection>,
236-
enable_polling: Arc<Topic<bool>>,
237-
channels: Arc<Topic<Channels>>,
238-
slot_status: Arc<Topic<Arc<SlotStatus>>>,
239-
name: String,
240-
) {
241-
let proxy = InstallerProxy::new(&conn).await.unwrap();
242-
243-
let mut retry_interval = RETRY_INTERVAL_MIN;
244-
245-
while let Some(mut channel) = channels
246-
.try_get()
247-
.and_then(|chs| chs.into_vec().into_iter().find(|ch| ch.name == name))
248-
{
249-
// Make sure update polling is enabled before doing anything,
250-
// as contacting the update server requires user consent.
251-
enable_polling.wait_for(true).await;
252-
253-
let polling_interval = channel.polling_interval;
254-
let slot_status = slot_status.try_get();
255-
256-
if let Err(e) = channel.poll(&proxy, slot_status.as_deref()).await {
257-
warn!(
258-
"Failed to fetch update for update channel \"{}\": {}. Retrying in {}s.",
259-
channel.name,
260-
e,
261-
retry_interval.as_secs()
262-
);
263-
264-
if retry_interval < RETRY_INTERVAL_MAX {
265-
sleep(retry_interval).await;
266-
267-
// Perform a (limited) exponential backoff on the retry interval to recover
268-
// fast from short-term issues while also preventing the update server from
269-
// being DDOSed by excessive retries.
270-
retry_interval *= 2;
271-
272-
continue;
273-
}
274-
}
275-
276-
retry_interval = RETRY_INTERVAL_MIN;
277-
278-
channels.modify(|chs| {
279-
let mut chs = chs?;
280-
let channel_prev = chs.iter_mut().find(|ch| ch.name == name)?;
281-
282-
// Check if the bundle we polled is the same as before and we don't need
283-
// to send a message to the subscribers.
284-
if *channel_prev == channel {
285-
return None;
286-
}
287-
288-
// Update the channel description with the newly polled bundle info
289-
*channel_prev = channel;
290-
291-
Some(chs)
292-
});
293-
294-
match polling_interval {
295-
Some(pi) => sleep(pi).await,
296-
None => break,
297-
}
298-
}
299-
}
300-
301185
async fn channel_list_update_task(
302-
conn: Arc<Connection>,
303186
mut reload_stream: Receiver<bool>,
304-
enable_polling: Arc<Topic<bool>>,
305187
channels: Arc<Topic<Channels>>,
306-
slot_status: Arc<Topic<Arc<SlotStatus>>>,
307188
) -> Result<()> {
308-
let mut previous: Option<Instant> = None;
309-
let mut polling_tasks: Vec<JoinHandle<_>> = Vec::new();
310-
311189
while let Some(reload) = reload_stream.next().await {
312190
if !reload {
313191
continue;
314192
}
315193

316-
// Polling for updates is a somewhat expensive operation.
317-
// Make sure it can not be abused to DOS the tacd.
318-
if previous
319-
.map(|p| p.elapsed() < RELOAD_RATE_LIMIT)
320-
.unwrap_or(false)
321-
{
322-
continue;
323-
}
324-
325194
// Read the list of available update channels
326195
let new_channels = match Channels::from_directory(CHANNELS_DIR) {
327196
Ok(chs) => chs,
@@ -331,29 +200,7 @@ async fn channel_list_update_task(
331200
}
332201
};
333202

334-
// Stop the currently running polling tasks
335-
for task in polling_tasks.drain(..) {
336-
task.cancel().await;
337-
}
338-
339-
let names: Vec<String> = new_channels.iter().map(|c| c.name.clone()).collect();
340-
341203
channels.set(new_channels);
342-
343-
// Spawn new polling tasks. They will poll once immediately.
344-
for name in names.into_iter() {
345-
let polling_task = spawn(channel_polling_task(
346-
conn.clone(),
347-
enable_polling.clone(),
348-
channels.clone(),
349-
slot_status.clone(),
350-
name,
351-
));
352-
353-
polling_tasks.push(polling_task);
354-
}
355-
356-
previous = Some(Instant::now());
357204
}
358205

359206
Ok(())
@@ -398,13 +245,7 @@ impl Rauc {
398245
let (reload_stream, _) = inst.reload.clone().subscribe_unbounded();
399246
wtb.spawn_task(
400247
"rauc-channel-list-update",
401-
channel_list_update_task(
402-
Arc::new(Connection),
403-
reload_stream,
404-
inst.enable_polling.clone(),
405-
inst.channels.clone(),
406-
inst.slot_status.clone(),
407-
),
248+
channel_list_update_task(reload_stream, inst.channels.clone()),
408249
)?;
409250

410251
Ok(inst)
@@ -422,7 +263,6 @@ impl Rauc {
422263
let operation = inst.operation.clone();
423264
let slot_status = inst.slot_status.clone();
424265
let primary = inst.primary.clone();
425-
let channels = inst.channels.clone();
426266
let should_reboot = inst.should_reboot.clone();
427267

428268
wtb.spawn_task("rauc-slot-status-update", async move {
@@ -485,23 +325,6 @@ impl Rauc {
485325
})
486326
.collect();
487327

488-
// Update the `newer_than_installed` field for the upstream bundles inside
489-
// of the update channels.
490-
channels.modify(|prev| {
491-
let prev = prev?;
492-
493-
let mut new = prev.clone();
494-
495-
for ch in new.iter_mut() {
496-
if let Some(bundle) = ch.bundle.as_mut() {
497-
bundle.update_install(&slots);
498-
}
499-
}
500-
501-
// Only send out messages if anything changed
502-
(new != prev).then_some(new)
503-
});
504-
505328
// Provide a simple yes/no "should reboot into other slot?" information
506329
// based on the bundle versions in the booted slot and the other slot.
507330
match would_reboot_into_other_slot(&slots, new_primary) {
@@ -608,13 +431,7 @@ impl Rauc {
608431
let (reload_stream, _) = inst.reload.clone().subscribe_unbounded();
609432
wtb.spawn_task(
610433
"rauc-channel-list-update",
611-
channel_list_update_task(
612-
conn.clone(),
613-
reload_stream,
614-
inst.enable_polling.clone(),
615-
inst.channels.clone(),
616-
inst.slot_status.clone(),
617-
),
434+
channel_list_update_task(reload_stream, inst.channels.clone()),
618435
)?;
619436

620437
Ok(inst)

0 commit comments

Comments
 (0)