Skip to content

Commit

Permalink
feat(update-agent): publishing update-agent progress to dbus (#349)
Browse files Browse the repository at this point in the history
* feat(update-agent): publishing update-agent progress to dbus

* adding detailed reporting

* ryan review 1

* review vol 2

* missing signal

* Working Signals

* review vol 3

---------

Co-authored-by: Ryan Butler <thebutlah@gmail.com>
  • Loading branch information
sfikastheo and TheButlah authored Jan 28, 2025
1 parent d61e38e commit 9a58dd1
Show file tree
Hide file tree
Showing 10 changed files with 297 additions and 41 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ orb-security-utils.path = "security-utils"
orb-slot-ctrl.path = "slot-ctrl"
orb-telemetry.path = "telemetry"
orb-update-agent-core.path = "update-agent/core"
orb-update-agent-dbus.path = "update-agent/dbus"
orb-zbus-proxies.path = "zbus-proxies"
seek-camera.path = "seek-camera/wrapper"

Expand Down
2 changes: 1 addition & 1 deletion update-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ once_cell = "1.17.0"
orb-build-info.workspace = true
orb-telemetry.workspace = true
orb-update-agent-core.workspace = true
orb-update-agent-dbus.workspace = true
orb-zbus-proxies = { workspace = true, features = ["login1"] }
polling = "2.2.0"
serde = { workspace = true, features = ["derive"] }
Expand All @@ -50,7 +51,6 @@ url = "2.2.2"
xz2 = "0.1.6"
zbus.workspace = true


[dependencies.update-agent-can]
git = "https://github.com/worldcoin/orb-software"
rev = "f13df5b723272efc55abf22cacce3625bbd1af04"
Expand Down
15 changes: 15 additions & 0 deletions update-agent/dbus/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "orb-update-agent-dbus"
version = "0.0.0"
authors = ["Theodore Sfikas <theodore.sfikas@toolsforhumanity.com>"]
description = "Dbus proxy and interface for orb-update-agent"
publish = false

edition.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true

[dependencies]
zbus.workspace = true
serde.workspace = true
66 changes: 66 additions & 0 deletions update-agent/dbus/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//! Query the current update status:
//! ```bash
//! gdbus call --session -d org.worldcoin.UpdateAgentManager1 -o \
//! '/org/worldcoin/UpdateAgentManager1' -m \
//! org.freedesktop.DBus.Properties.Get org.worldcoin.UpdateAgentManager1 Progress
//! ```
//!
//! Monitor for signals:
//! ```bash
//! export DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/worldcoin_bus_socket
//! dbus-monitor --session type='signal',sender='org.worldcoin.UpdateAgentManager1'
//! ```
use serde::{Deserialize, Serialize};
use zbus::interface;
use zbus::zvariant::{OwnedValue, Type, Value};

/// A trait representing update progress behavior.
///
/// This trait is implemented by types that can provide information about the current update status.
/// It abstracts the behavior to allow multiple implementations, enabling dependency injection,
/// mocking for tests, and sharing the same interface across both client and server code.
pub trait UpdateAgentManagerT: Send + Sync + 'static {
fn progress(&self) -> Vec<ComponentStatus>;
}

/// A wrapper struct for types implementing [`UpdateAgentManagerT`].
pub struct UpdateAgentManager<T>(pub T);

#[derive(
Debug, Serialize, Deserialize, Type, Clone, Copy, Eq, PartialEq, Value, OwnedValue,
)]
pub enum ComponentState {
None = 1,
Downloading = 2,
Fetched = 3,
Processed = 4,
Installed = 5,
}

#[derive(
Debug, Serialize, Deserialize, Type, Eq, PartialEq, Clone, Value, OwnedValue,
)]
pub struct ComponentStatus {
/// Component Name
pub name: String,
/// Current state of acomponent
pub state: ComponentState,
/// Progress through the current state (0-100)
pub progress: u8,
}

/// DBus interface implementation for [`UpdateProgress`].
#[interface(
name = "org.worldcoin.UpdateAgentManager1",
proxy(
default_service = "org.worldcoin.UpdateAgentManager1",
default_path = "/org/worldcoin/UpdateAgentManager1",
)
)]
impl<T: UpdateAgentManagerT> UpdateAgentManagerT for UpdateAgentManager<T> {
#[zbus(property)]
fn progress(&self) -> Vec<ComponentStatus> {
self.0.progress()
}
}
36 changes: 30 additions & 6 deletions update-agent/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,22 @@ use orb_update_agent_core::{
components, manifest::InstallationPhase, Claim, LocalOrRemote, ManifestComponent,
MimeType, Slot, Source,
};
use orb_update_agent_dbus::{ComponentState, UpdateAgentManager};
use reqwest::{
header::{ToStrError, CONTENT_LENGTH, RANGE},
Url,
};
use tracing::{info, warn};

use crate::{dbus, update::Update as _, util};
use zbus::blocking::object_server::InterfaceRef;

use crate::{
dbus::{
interfaces::{self, UpdateProgress},
proxies,
},
update::Update as _,
util,
};

const CHUNK_SIZE: u32 = 4 * 1024 * 1024;

Expand Down Expand Up @@ -292,13 +301,15 @@ fn extract<P: AsRef<Path>>(path: P, uncompressed_download_path: P) -> eyre::Resu
}

#[expect(clippy::result_large_err)]
#[expect(clippy::too_many_arguments)]
pub fn download<P: AsRef<Path>>(
url: &Url,
name: &str,
unique_name: &str,
size: u64,
dst_dir: &P,
supervisor_proxy: Option<&dbus::SupervisorProxyBlocking<'static>>,
supervisor_proxy: Option<&proxies::SupervisorProxyBlocking<'static>>,
update_iface: Option<&InterfaceRef<UpdateAgentManager<UpdateProgress>>>,
download_delay: Duration,
) -> Result<PathBuf, Error> {
let component_path = util::make_component_path(dst_dir, unique_name);
Expand Down Expand Up @@ -427,10 +438,21 @@ pub fn download<P: AsRef<Path>>(
{
if progress_percent != current_progress_percent {
progress_percent = current_progress_percent;
info!("downloading component `{name}`: {progress_percent}%");
}
} else {
info!("downloading component `{name}`: 100%");
progress_percent = 100;
}

info!("downloading component `{name}`: {progress_percent}%");
if let Some(iface) = update_iface {
if let Err(e) = interfaces::update_dbus_properties(
name,
ComponentState::Downloading,
progress_percent as u8,
iface,
) {
warn!("{e:?}");
}
}

// We are using `downloads_allowed` as a proxy to set/unset the sleep duration for now.
Expand Down Expand Up @@ -492,7 +514,8 @@ pub fn fetch<P: AsRef<Path>>(
system_component: &components::Component,
source: &Source,
dst_dir: P,
supervisor: Option<&dbus::SupervisorProxyBlocking<'static>>,
supervisor: Option<&proxies::SupervisorProxyBlocking<'static>>,
update_iface: Option<&InterfaceRef<UpdateAgentManager<UpdateProgress>>>,
download_delay: Duration,
) -> Result<Component, Error> {
let path = match &source.url {
Expand All @@ -504,6 +527,7 @@ pub fn fetch<P: AsRef<Path>>(
source.size,
&dst_dir,
supervisor,
update_iface,
download_delay,
)?,
};
Expand Down
53 changes: 53 additions & 0 deletions update-agent/src/dbus/interfaces.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use eyre::WrapErr;
use orb_update_agent_core::ManifestComponent;
use orb_update_agent_dbus::{
ComponentState, ComponentStatus, UpdateAgentManager, UpdateAgentManagerT,
};
use zbus::blocking::object_server::InterfaceRef;

#[derive(Debug, Clone, Default)]
pub struct UpdateProgress {
pub components: Vec<ComponentStatus>,
}

impl UpdateAgentManagerT for UpdateProgress {
fn progress(&self) -> Vec<ComponentStatus> {
self.components.clone()
}
}

pub fn init_dbus_properties(
components: &[ManifestComponent],
iface: &InterfaceRef<UpdateAgentManager<UpdateProgress>>,
) {
iface.get_mut().0.components = components
.iter()
.map(|c| ComponentStatus {
name: c.name.clone(),
state: ComponentState::None,
progress: 0,
})
.collect();
}

pub fn update_dbus_properties(
name: &str,
state: ComponentState,
progress: u8,
iface: &InterfaceRef<UpdateAgentManager<UpdateProgress>>,
) -> eyre::Result<()> {
if let Some(component) = iface
.get_mut()
.0
.components
.iter_mut()
.find(|c| c.name == name)
{
component.state = state;
component.progress = progress;
}
zbus::block_on(iface.get_mut().progress_changed(iface.signal_context()))
.wrap_err("Failed to emit progress_changed signal")?;

Ok(())
}
2 changes: 2 additions & 0 deletions update-agent/src/dbus/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod interfaces;
pub mod proxies;
File renamed without changes.
Loading

0 comments on commit 9a58dd1

Please sign in to comment.