15
15
// with this program; if not, write to the Free Software Foundation, Inc.,
16
16
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
17
18
- use std:: cmp:: Ordering ;
19
18
use std:: collections:: HashMap ;
20
- use std:: time:: { Duration , Instant } ;
21
19
22
20
use anyhow:: Result ;
23
21
use async_std:: channel:: Receiver ;
24
22
use async_std:: stream:: StreamExt ;
25
23
use async_std:: sync:: Arc ;
26
- use async_std:: task:: { sleep, spawn, JoinHandle } ;
27
24
use log:: warn;
28
25
use serde:: { Deserialize , Serialize } ;
29
26
@@ -48,38 +45,6 @@ use installer::InstallerProxy;
48
45
49
46
#[ cfg( feature = "demo_mode" ) ]
50
47
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
-
83
48
pub ( super ) const CHANNELS_DIR : & str = "demo_files/usr/share/tacd/update_channels" ;
84
49
}
85
50
@@ -91,10 +56,6 @@ mod imports {
91
56
pub ( super ) const CHANNELS_DIR : & str = "/usr/share/tacd/update_channels" ;
92
57
}
93
58
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
-
98
59
use imports:: * ;
99
60
100
61
#[ derive( Serialize , Deserialize , Clone ) ]
@@ -158,20 +119,10 @@ pub struct Rauc {
158
119
pub channels : Arc < Topic < Channels > > ,
159
120
pub reload : Arc < Topic < bool > > ,
160
121
pub should_reboot : Arc < Topic < bool > > ,
122
+ #[ allow( dead_code) ]
161
123
pub enable_polling : Arc < Topic < bool > > ,
162
124
}
163
125
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
-
175
126
#[ cfg( not( feature = "demo_mode" ) ) ]
176
127
fn would_reboot_into_other_slot ( slot_status : & SlotStatus , primary : Option < String > ) -> Result < bool > {
177
128
let rootfs_0 = slot_status. get ( "rootfs_0" ) ;
@@ -231,97 +182,15 @@ fn would_reboot_into_other_slot(slot_status: &SlotStatus, primary: Option<String
231
182
}
232
183
}
233
184
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
-
301
185
async fn channel_list_update_task (
302
- conn : Arc < Connection > ,
303
186
mut reload_stream : Receiver < bool > ,
304
- enable_polling : Arc < Topic < bool > > ,
305
187
channels : Arc < Topic < Channels > > ,
306
- slot_status : Arc < Topic < Arc < SlotStatus > > > ,
307
188
) -> Result < ( ) > {
308
- let mut previous: Option < Instant > = None ;
309
- let mut polling_tasks: Vec < JoinHandle < _ > > = Vec :: new ( ) ;
310
-
311
189
while let Some ( reload) = reload_stream. next ( ) . await {
312
190
if !reload {
313
191
continue ;
314
192
}
315
193
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
-
325
194
// Read the list of available update channels
326
195
let new_channels = match Channels :: from_directory ( CHANNELS_DIR ) {
327
196
Ok ( chs) => chs,
@@ -331,29 +200,7 @@ async fn channel_list_update_task(
331
200
}
332
201
} ;
333
202
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
-
341
203
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 ( ) ) ;
357
204
}
358
205
359
206
Ok ( ( ) )
@@ -398,13 +245,7 @@ impl Rauc {
398
245
let ( reload_stream, _) = inst. reload . clone ( ) . subscribe_unbounded ( ) ;
399
246
wtb. spawn_task (
400
247
"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 ( ) ) ,
408
249
) ?;
409
250
410
251
Ok ( inst)
@@ -422,7 +263,6 @@ impl Rauc {
422
263
let operation = inst. operation . clone ( ) ;
423
264
let slot_status = inst. slot_status . clone ( ) ;
424
265
let primary = inst. primary . clone ( ) ;
425
- let channels = inst. channels . clone ( ) ;
426
266
let should_reboot = inst. should_reboot . clone ( ) ;
427
267
428
268
wtb. spawn_task ( "rauc-slot-status-update" , async move {
@@ -485,23 +325,6 @@ impl Rauc {
485
325
} )
486
326
. collect ( ) ;
487
327
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
-
505
328
// Provide a simple yes/no "should reboot into other slot?" information
506
329
// based on the bundle versions in the booted slot and the other slot.
507
330
match would_reboot_into_other_slot ( & slots, new_primary) {
@@ -608,13 +431,7 @@ impl Rauc {
608
431
let ( reload_stream, _) = inst. reload . clone ( ) . subscribe_unbounded ( ) ;
609
432
wtb. spawn_task (
610
433
"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 ( ) ) ,
618
435
) ?;
619
436
620
437
Ok ( inst)
0 commit comments