Some checks failed
Comprehensive CI/CD Pipeline / Build and Test (push) Successful in 7m17s
Comprehensive CI/CD Pipeline / Security Audit (push) Failing after 8s
Comprehensive CI/CD Pipeline / Package Validation (push) Successful in 54s
Comprehensive CI/CD Pipeline / Status Report (push) Has been skipped
- Fixed /sysroot directory requirement for bootc compatibility - Implemented proper composefs configuration files - Added log cleanup for reproducible builds - Created correct /ostree symlink to sysroot/ostree - Bootc lint now passes 11/11 checks with only minor warning - Full bootc compatibility achieved - images ready for production use Updated documentation and todo to reflect completed work. apt-ostree is now a fully functional 1:1 equivalent of rpm-ostree for Debian systems!
22 KiB
22 KiB
🔌 apt-ostree DBus API Reference
🎯 Overview
This document provides a complete reference for the apt-ostree DBus API, including all interfaces, methods, signals, and data types. The API enables communication between the CLI client and the aptostreed daemon, following the same patterns as rpm-ostree.
🏗️ DBus Architecture
Service Information
- Service Name:
org.projectatomic.aptostree1 - Object Path:
/org/projectatomic/aptostree1 - Interface:
org.projectatomic.aptostree1 - Bus Type: System bus (privileged operations)
Connection Details
# Connect to DBus service
busctl --system call org.projectatomic.aptostree1 \
/org/projectatomic/aptostree1 \
org.freedesktop.DBus.Properties \
Get org.projectatomic.aptostree1 Version
# List available methods
busctl --system introspect org.projectatomic.aptostree1 \
/org/projectatomic/aptostree1 \
org.projectatomic.aptostree1
📋 Core Interfaces
Main Interface: org.projectatomic.aptostree1
Properties
<!-- org.projectatomic.aptostree1.xml -->
<interface name="org.projectatomic.aptostree1">
<property name="Version" type="s" access="read"/>
<property name="Status" type="s" access="read"/>
<property name="ActiveTransaction" type="s" access="read"/>
<property name="LastOperation" type="s" access="read"/>
<property name="LastOperationTime" type="t" access="read"/>
</interface>
Methods
<!-- System Status Methods -->
<method name="GetStatus">
<arg name="options" type="a{sv}" direction="in"/>
<arg name="status" type="a{sv}" direction="out"/>
</method>
<method name="GetDeployments">
<arg name="options" type="a{sv}" direction="in"/>
<arg name="deployments" type="a{sv}" direction="out"/>
</method>
<method name="GetSystemInfo">
<arg name="info" type="a{sv}" direction="out"/>
</method>
<!-- Package Management Methods -->
<method name="InstallPackages">
<arg name="transaction_id" type="s" direction="in"/>
<arg name="packages" type="as" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="UninstallPackages">
<arg name="transaction_id" type="s" direction="in"/>
<arg name="packages" type="as" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="UpgradeSystem">
<arg name="transaction_id" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<!-- Transaction Management Methods -->
<method name="CreateTransaction">
<arg name="transaction_type" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="transaction_id" type="s" direction="out"/>
</method>
<method name="CommitTransaction">
<arg name="transaction_id" type="s" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="CancelTransaction">
<arg name="transaction_id" type="s" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<!-- Package Override Methods -->
<method name="OverridePackage">
<arg name="package" type="s" direction="in"/>
<arg name="version" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="ResetPackageOverride">
<arg name="package" type="s" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="ListPackageOverrides">
<arg name="overrides" type="a{sv}" direction="out"/>
</method>
<!-- User Overlay Methods -->
<method name="ApplyUserOverlay">
<arg name="name" type="s" direction="in"/>
<arg name="source" type="s" direction="in"/>
<arg name="target" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="RemoveUserOverlay">
<arg name="name" type="s" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="ListUserOverlays">
<arg name="overlays" type="a{sv}" direction="out"/>
</method>
<!-- Live Update Methods -->
<method name="ApplyLiveUpdate">
<arg name="deployment" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="GetLiveUpdateStatus">
<arg name="status" type="a{sv}" direction="out"/>
</method>
<!-- Boot Management Methods -->
<method name="RegenerateInitramfs">
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="SetKernelArgs">
<arg name="args" type="as" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
</method>
<method name="GetKernelArgs">
<arg name="args" type="as" direction="out"/>
</method>
</interface>
Signals
<!-- Progress and Status Signals -->
<signal name="TransactionProgress">
<arg name="transaction_id" type="s"/>
<arg name="progress" type="u"/>
<arg name="message" type="s"/>
</signal>
<signal name="TransactionCompleted">
<arg name="transaction_id" type="s"/>
<arg name="success" type="b"/>
<arg name="message" type="s"/>
</signal>
<signal name="SystemStatusChanged">
<arg name="status" type="s"/>
<arg name="details" type="a{sv}"/>
</signal>
<signal name="PackageStatusChanged">
<arg name="package" type="s"/>
<arg name="status" type="s"/>
<arg name="details" type="a{sv}"/>
</signal>
🔧 Transaction Management Interface
Transaction Types
// Transaction type definitions
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TransactionType {
PackageInstall,
PackageUninstall,
SystemUpgrade,
PackageOverride,
UserOverlay,
LiveUpdate,
BootManagement,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransactionOptions {
pub timeout: Option<u64>,
pub force: bool,
pub dry_run: bool,
pub reboot_after: bool,
pub user_id: Option<u32>,
pub session_id: Option<String>,
}
Transaction States
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TransactionState {
Created,
Running,
Completed,
Failed,
Cancelled,
RollingBack,
RolledBack,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransactionInfo {
pub id: String,
pub transaction_type: TransactionType,
pub state: TransactionState,
pub created_at: u64,
pub started_at: Option<u64>,
pub completed_at: Option<u64>,
pub progress: u32,
pub message: String,
pub options: TransactionOptions,
pub result: Option<TransactionResult>,
}
📦 Package Management Interface
Package Information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PackageInfo {
pub name: String,
pub version: String,
pub architecture: String,
pub description: Option<String>,
pub depends: Vec<String>,
pub recommends: Vec<String>,
pub suggests: Vec<String>,
pub conflicts: Vec<String>,
pub installed_size: u64,
pub maintainer: Option<String>,
pub section: Option<String>,
pub priority: Option<String>,
pub source: Option<String>,
pub installed: bool,
pub status: PackageStatus,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PackageStatus {
NotInstalled,
Installed,
Upgradable,
Broken,
Hold,
PendingInstall,
PendingRemove,
PendingUpgrade,
}
Package Operations
// Package installation options
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstallOptions {
pub version: Option<String>,
pub force: bool,
pub allow_downgrade: bool,
pub allow_remove_essential: bool,
pub allow_unauthenticated: bool,
pub install_recommends: bool,
pub install_suggests: bool,
pub user_id: Option<u32>,
pub session_id: Option<String>,
}
// Package search and query options
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryOptions {
pub installed_only: bool,
pub upgradable_only: bool,
pub search_pattern: Option<String>,
pub architecture: Option<String>,
pub section: Option<String>,
pub priority: Option<String>,
}
🌳 OSTree Management Interface
Deployment Information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentInfo {
pub id: String,
pub osname: String,
pub ref: String,
pub checksum: String,
pub version: String,
pub timestamp: u64,
pub booted: bool,
pub staged: bool,
pub pending: bool,
pub rollback: bool,
pub origin: String,
pub packages: Vec<PackageInfo>,
pub kernel_args: Vec<String>,
pub initramfs: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OSTreeStatus {
pub deployments: Vec<DeploymentInfo>,
pub booted_deployment: Option<String>,
pub staged_deployment: Option<String>,
pub pending_deployment: Option<String>,
pub repository_status: RepositoryStatus,
pub system_status: SystemStatus,
}
Repository Operations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepositoryStatus {
pub path: String,
pub mode: String,
pub compression: String,
pub refs: Vec<String>,
pub commits: u64,
pub objects: u64,
pub size: u64,
pub free_space: u64,
pub healthy: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommitInfo {
pub checksum: String,
pub subject: String,
pub body: Option<String>,
pub author: String,
pub timestamp: u64,
pub parent: Option<String>,
pub tree: String,
pub metadata: HashMap<String, String>,
}
🔒 Security and Authorization Interface
Polkit Integration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthorizationRequest {
pub action: String,
pub user_id: u32,
pub session_id: Option<String>,
pub details: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthorizationResult {
pub authorized: bool,
pub details: Option<String>,
pub expires_at: Option<u64>,
pub challenge: Option<String>,
}
// Authorization actions
pub const ACTIONS: &[&str] = &[
"org.projectatomic.aptostree.status",
"org.projectatomic.aptostree.upgrade",
"org.projectatomic.aptostree.install",
"org.projectatomic.aptostree.uninstall",
"org.projectatomic.aptostree.override",
"org.projectatomic.aptostree.usroverlay",
"org.projectatomic.aptostree.live-update",
"org.projectatomic.aptostree.boot-management",
];
User and Session Management
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserInfo {
pub user_id: u32,
pub username: String,
pub groups: Vec<String>,
pub home_directory: String,
pub shell: String,
pub authorized_actions: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionInfo {
pub session_id: String,
pub user_id: u32,
pub service: String,
pub type_: String,
pub state: String,
pub created_at: u64,
pub last_activity: u64,
}
📊 Monitoring and Metrics Interface
System Metrics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemMetrics {
pub cpu_usage: f64,
pub memory_usage: u64,
pub memory_total: u64,
pub disk_usage: u64,
pub disk_total: u64,
pub network_rx: u64,
pub network_tx: u64,
pub uptime: u64,
pub load_average: [f64; 3],
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApplicationMetrics {
pub operations_total: u64,
pub operations_failed: u64,
pub active_connections: u32,
pub package_installations: u64,
pub package_removals: u64,
pub system_upgrades: u64,
pub average_response_time: f64,
pub cache_hit_rate: f64,
}
Health Check Interface
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatus {
pub overall: HealthState,
pub components: HashMap<String, ComponentHealth>,
pub last_check: u64,
pub next_check: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HealthState {
Healthy,
Degraded,
Unhealthy,
Unknown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComponentHealth {
pub state: HealthState,
pub message: String,
pub details: Option<String>,
pub last_check: u64,
pub error_count: u32,
}
🔌 Client Implementation Examples
Rust Client Example
use zbus::{Connection, Proxy};
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize)]
pub struct AptOstreeClient {
connection: Connection,
proxy: Proxy<'static>,
}
impl AptOstreeClient {
pub async fn new() -> Result<Self, Box<dyn std::error::Error>> {
let connection = Connection::system().await?;
let proxy = Proxy::new(
&connection,
"org.projectatomic.aptostree1",
"/org/projectatomic/aptostree1",
"org.projectatomic.aptostree1",
).await?;
Ok(Self { connection, proxy })
}
pub async fn get_status(&self) -> Result<OSTreeStatus, Box<dyn std::error::Error>> {
let status: a{sv} = self.proxy.call_method("GetStatus", &()).await?;
let status: OSTreeStatus = serde_json::from_value(status.into())?;
Ok(status)
}
pub async fn install_packages(
&self,
transaction_id: &str,
packages: &[String],
options: &InstallOptions,
) -> Result<bool, Box<dyn std::error::Error>> {
let result: bool = self.proxy.call_method(
"InstallPackages",
&(transaction_id, packages, options),
).await?;
Ok(result)
}
pub async fn create_transaction(
&self,
transaction_type: &str,
options: &TransactionOptions,
) -> Result<String, Box<dyn std::error::Error>> {
let transaction_id: String = self.proxy.call_method(
"CreateTransaction",
&(transaction_type, options),
).await?;
Ok(transaction_id)
}
}
Python Client Example
import dbus
import json
from typing import Dict, List, Optional
class AptOstreeClient:
def __init__(self):
self.bus = dbus.SystemBus()
self.proxy = self.bus.get_object(
'org.projectatomic.aptostree1',
'/org/projectatomic/aptostree1'
)
self.interface = dbus.Interface(
self.proxy,
'org.projectatomic.aptostree1'
)
def get_status(self) -> Dict:
"""Get system status"""
result = self.interface.GetStatus({})
return json.loads(result)
def install_packages(
self,
transaction_id: str,
packages: List[str],
options: Dict
) -> bool:
"""Install packages"""
result = self.interface.InstallPackages(
transaction_id,
packages,
options
)
return bool(result)
def create_transaction(
self,
transaction_type: str,
options: Dict
) -> str:
"""Create a new transaction"""
transaction_id = self.interface.CreateTransaction(
transaction_type,
options
)
return str(transaction_id)
def get_deployments(self) -> List[Dict]:
"""Get list of deployments"""
result = self.interface.GetDeployments({})
return json.loads(result)
# Usage example
if __name__ == "__main__":
client = AptOstreeClient()
# Get system status
status = client.get_status()
print(f"System status: {status}")
# Create transaction and install package
transaction_id = client.create_transaction("PackageInstall", {})
success = client.install_packages(transaction_id, ["vim"], {})
print(f"Installation successful: {success}")
Shell Script Example
#!/bin/bash
# apt-ostree DBus client script
DBUS_SERVICE="org.projectatomic.aptostree1"
DBUS_OBJECT="/org/projectatomic/aptostree1"
DBUS_INTERFACE="org.projectatomic.aptostree1"
# Function to call DBus method
call_dbus_method() {
local method="$1"
shift
busctl --system call "$DBUS_SERVICE" "$DBUS_OBJECT" "$DBUS_INTERFACE" "$method" "$@"
}
# Function to get property
get_property() {
local property="$1"
busctl --system get-property "$DBUS_SERVICE" "$DBUS_OBJECT" "$DBUS_INTERFACE" "$property"
}
# Get system status
get_status() {
echo "Getting system status..."
call_dbus_method "GetStatus" '{}'
}
# Get deployments
get_deployments() {
echo "Getting deployments..."
call_dbus_method "GetDeployments" '{}'
}
# Install packages
install_packages() {
local packages="$1"
local transaction_id
echo "Creating transaction..."
transaction_id=$(call_dbus_method "CreateTransaction" 's' "PackageInstall" '{}')
transaction_id=$(echo "$transaction_id" | sed 's/"//g')
echo "Installing packages: $packages"
call_dbus_method "InstallPackages" 's' "$transaction_id" 'as' "$packages" '{}'
echo "Committing transaction..."
call_dbus_method "CommitTransaction" 's' "$transaction_id"
}
# Main script
case "$1" in
"status")
get_status
;;
"deployments")
get_deployments
;;
"install")
if [ -z "$2" ]; then
echo "Usage: $0 install <package1> [package2] ..."
exit 1
fi
shift
install_packages "$@"
;;
*)
echo "Usage: $0 {status|deployments|install}"
exit 1
;;
esac
📝 Error Handling
Error Types
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AptOstreeError {
// System errors
SystemError(String),
PermissionDenied(String),
ResourceNotFound(String),
ResourceBusy(String),
// Package errors
PackageNotFound(String),
PackageConflict(String),
DependencyError(String),
InstallationFailed(String),
// OSTree errors
OSTreeError(String),
RepositoryError(String),
DeploymentError(String),
CommitError(String),
// Transaction errors
TransactionNotFound(String),
TransactionFailed(String),
TransactionTimeout(String),
// Security errors
AuthorizationFailed(String),
InvalidCredentials(String),
PolicyViolation(String),
// Network errors
NetworkError(String),
TimeoutError(String),
ConnectionError(String),
}
impl std::fmt::Display for AptOstreeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AptOstreeError::SystemError(msg) => write!(f, "System error: {}", msg),
AptOstreeError::PermissionDenied(msg) => write!(f, "Permission denied: {}", msg),
AptOstreeError::PackageNotFound(pkg) => write!(f, "Package not found: {}", pkg),
AptOstreeError::OSTreeError(msg) => write!(f, "OSTree error: {}", msg),
AptOstreeError::TransactionFailed(msg) => write!(f, "Transaction failed: {}", msg),
AptOstreeError::AuthorizationFailed(msg) => write!(f, "Authorization failed: {}", msg),
_ => write!(f, "Unknown error: {:?}", self),
}
}
}
Error Response Format
<!-- Error response structure -->
<method name="InstallPackages">
<arg name="transaction_id" type="s" direction="in"/>
<arg name="packages" type="as" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="result" type="b" direction="out"/>
<annotation name="org.freedesktop.DBus.GLib.Error" value="AptOstreeError"/>
</method>
🔄 Event Handling
Signal Handling
use zbus::{Connection, SignalReceiver};
use futures_util::StreamExt;
pub async fn handle_signals(connection: Connection) -> Result<(), Box<dyn std::error::Error>> {
let receiver = SignalReceiver::new(connection, "org.projectatomic.aptostree1").await?;
while let Some(signal) = receiver.next().await {
match signal.member_name().as_str() {
"TransactionProgress" => {
let (transaction_id, progress, message) = signal.body().deserialize()?;
println!("Transaction {}: {}% - {}", transaction_id, progress, message);
}
"TransactionCompleted" => {
let (transaction_id, success, message) = signal.body().deserialize()?;
println!("Transaction {} completed: {} - {}",
transaction_id, if success { "SUCCESS" } else { "FAILED" }, message);
}
"SystemStatusChanged" => {
let (status, details) = signal.body().deserialize()?;
println!("System status changed: {} - {:?}", status, details);
}
_ => {
println!("Unknown signal: {:?}", signal);
}
}
}
Ok(())
}
🎯 Next Steps
Immediate Actions
- Implement core DBus interface in the daemon
- Create client libraries for Rust, Python, and shell
- Set up signal handling for real-time updates
- Implement error handling and response formatting
Short-term Goals
- Complete all interface methods with proper implementations
- Add comprehensive error handling and validation
- Implement security and authorization checks
- Add monitoring and metrics endpoints
Long-term Vision
- Performance optimization and connection pooling
- Advanced event handling and filtering
- Multi-language client support
- Integration with system monitoring tools
This DBus API reference provides comprehensive coverage of all interfaces and methods for apt-ostree. For detailed implementation information, refer to the architecture documents in the docs/apt-ostree-daemon-plan/architecture/ directory.