- Fix parallel execution logic to properly handle JoinHandle<Result<R, E>> types - Use join_all instead of try_join_all for proper Result handling - Fix double question mark (??) issue in parallel execution methods - Clean up unused imports in parallel and cache modules - Ensure all performance optimization modules compile successfully - Fix CI build failures caused by compilation errors
17 KiB
rpm-ostree Client-Daemon Architecture
Executive Summary
rpm-ostree uses a sophisticated client-daemon architecture that separates privileged system operations from unprivileged user interactions. This design provides security, reliability, and concurrent operation support while maintaining a clean user interface.
Architecture Overview
High-Level Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ CLI Client │ │ GUI Client │ │ API Client │
│ (rpmostree) │ │ (GNOME/KDE) │ │ (Python/Go) │
└─────────┬───────┘ └─────────┬───────┘ └─────────┬───────┘
│ │ │
└──────────────────────┼──────────────────────┘
│
┌─────────────▼─────────────┐
│ D-Bus Interface │
│ (org.projectatomic.rpmo │
│ stree1) │
└─────────────┬─────────────┘
│
┌─────────────▼─────────────┐
│ rpm-ostreed Daemon │
│ (Privileged Service) │
└─────────────┬─────────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
┌─────▼─────┐ ┌───────▼──────┐ ┌─────▼─────┐
│ libdnf │ │ libostree │ │ System │
│ (RPM/DNF) │ │ (Filesystem) │ │ Services │
└───────────┘ └──────────────┘ └───────────┘
Design Principles
- Privilege Separation: Daemon runs with elevated privileges, clients run unprivileged
- D-Bus Communication: Standard system service interface for inter-process communication
- Transaction Management: Atomic operations with rollback capability
- Concurrent Operations: Multiple clients can interact simultaneously
- State Persistence: Daemon maintains system state across operations
Client Architecture
CLI Client (rpmostree)
Purpose: Command-line interface for user interaction
Key Components:
- Command Parser: Parse command-line arguments
- D-Bus Client: Communicate with daemon
- Progress Handler: Display operation progress
- Error Handler: Handle and display errors
Implementation:
class RpmOstreeClient {
// D-Bus client
std::unique_ptr<RpmOstreeClientLib> client_lib;
// Command dispatch
int dispatch_command(int argc, char* argv[]);
// D-Bus communication
bool connect_to_daemon();
void handle_daemon_error(const std::string& error);
// Progress handling
void handle_progress(const std::string& message, int percentage);
void handle_completion(const std::string& result);
};
Command Flow:
- Parse command-line arguments
- Connect to daemon via D-Bus
- Send operation request
- Handle progress updates
- Display results or errors
GUI Clients
Purpose: Graphical user interfaces for system management
Components:
- GNOME Software: Integration with GNOME Software Center
- KDE Discover: Integration with KDE Discover
- Custom GUIs: Third-party graphical interfaces
Implementation:
- Use D-Bus interface for system operations
- Provide user-friendly progress indicators
- Handle authentication via PolicyKit
- Display system status and deployment information
API Clients
Purpose: Programmatic interfaces for automation and integration
Components:
- Python Bindings: Python library for rpm-ostree operations
- Go Bindings: Go library for rpm-ostree operations
- REST APIs: HTTP-based interfaces (planned)
Implementation:
- Direct D-Bus communication
- High-level abstractions for common operations
- Error handling and recovery mechanisms
- Async operation support
Daemon Architecture
Core Daemon (rpm-ostreed)
Purpose: Centralized system service for privileged operations
Key Components:
- D-Bus Service: Expose system management interface
- Transaction Manager: Handle atomic operations
- State Manager: Maintain system state
- Resource Manager: Manage system resources
Implementation:
class RpmOstreeDaemon {
// Global state management
std::unique_ptr<RpmOstreeSysroot> sysroot;
std::unique_ptr<RpmOstreeOS> os;
// Transaction management
std::map<std::string, std::unique_ptr<RpmOstreeTransaction>> transactions;
// D-Bus interface
std::unique_ptr<GDBusObjectManagerServer> object_manager;
// Service management
void start_service();
void stop_service();
void handle_client_connection(GDBusConnection* connection);
};
Service Lifecycle:
- Initialize system components
- Register D-Bus service
- Start listening for client connections
- Handle client requests
- Clean up on shutdown
D-Bus Interface
Service Name: org.projectatomic.rpmostree1
Main Objects:
/org/projectatomic/rpmostree1/Sysroot: System root management/org/projectatomic/rpmostree1/OS: Operating system operations
Key Methods:
<interface name="org.projectatomic.rpmostree1.OS">
<method name="Upgrade">
<arg name="options" type="a{sv}" direction="in"/>
<arg name="transaction_address" type="s" direction="out"/>
</method>
<method name="Rollback">
<arg name="options" type="a{sv}" direction="in"/>
<arg name="transaction_address" type="s" direction="out"/>
</method>
<method name="Deploy">
<arg name="ref" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="transaction_address" type="s" direction="out"/>
</method>
<method name="Rebase">
<arg name="ref" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="transaction_address" type="s" direction="out"/>
</method>
<method name="PkgChange">
<arg name="packages" type="as" direction="in"/>
<arg name="change_type" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="transaction_address" type="s" direction="out"/>
</method>
<method name="KernelArgs">
<arg name="operation" type="s" direction="in"/>
<arg name="args" type="as" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="transaction_address" type="s" direction="out"/>
</method>
<method name="Cleanup">
<arg name="options" type="a{sv}" direction="in"/>
<arg name="transaction_address" type="s" direction="out"/>
</method>
</interface>
Signals:
<signal name="TransactionChanged">
<arg name="transaction_address" type="s"/>
<arg name="state" type="s"/>
<arg name="message" type="s"/>
<arg name="percentage" type="i"/>
</signal>
<signal name="TransactionCompleted">
<arg name="transaction_address" type="s"/>
<arg name="success" type="b"/>
<arg name="result" type="s"/>
</signal>
Transaction Management
Purpose: Handle atomic operations with rollback capability
Transaction Types:
- DeployTransaction: New deployment creation
- RollbackTransaction: Deployment rollback
- PkgChangeTransaction: Package installation/removal
- RebaseTransaction: Base image switching
- UpgradeTransaction: System upgrades
Implementation:
class RpmOstreeTransaction {
// Transaction state
TransactionState state;
std::string transaction_id;
TransactionType type;
// Rollback information
std::vector<RollbackPoint> rollback_points;
// Progress reporting
void emit_progress(const std::string& message, int percentage);
void emit_completion(bool success, const std::string& result);
// Atomic execution
bool execute_atomic();
void rollback_on_failure();
// State management
void set_state(TransactionState new_state);
TransactionState get_state() const;
};
Transaction Lifecycle:
- Initiation: Client requests operation
- Validation: Validate request parameters
- Preparation: Set up rollback points
- Execution: Perform operation with progress reporting
- Completion: Finalize operation or rollback
- Cleanup: Clean up resources
State Management
Purpose: Maintain system state across operations
State Components:
- Deployment State: Current and available deployments
- Package State: Installed and layered packages
- Configuration State: System configuration
- Transaction State: Active and completed transactions
Implementation:
class StateManager {
// System state
std::unique_ptr<DeploymentState> deployment_state;
std::unique_ptr<PackageState> package_state;
std::unique_ptr<ConfigurationState> config_state;
// State persistence
void save_state();
void load_state();
void sync_state();
// State queries
DeploymentInfo get_current_deployment();
std::vector<DeploymentInfo> get_available_deployments();
std::vector<PackageInfo> get_installed_packages();
};
Communication Protocol
D-Bus Communication
Connection Setup:
// Client connection
GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, nullptr);
// Service registration
GDBusObjectManagerServer* object_manager = g_dbus_object_manager_server_new("/org/projectatomic/rpmostree1");
Method Calls:
// Client method call
GVariant* result = g_dbus_connection_call_sync(
connection,
"org.projectatomic.rpmostree1",
"/org/projectatomic/rpmostree1/OS",
"org.projectatomic.rpmostree1.OS",
"Upgrade",
g_variant_new("(a{sv})", options),
nullptr,
G_DBUS_CALL_FLAGS_NONE,
-1,
nullptr,
nullptr
);
Signal Handling:
// Client signal connection
g_dbus_connection_signal_subscribe(
connection,
"org.projectatomic.rpmostree1",
"org.projectatomic.rpmostree1.OS",
"TransactionChanged",
"/org/projectatomic/rpmostree1/OS",
nullptr,
G_DBUS_SIGNAL_FLAGS_NONE,
handle_transaction_changed,
nullptr,
nullptr
);
Error Handling
Error Types:
- Network Errors: Package download failures
- Dependency Errors: Package dependency conflicts
- Filesystem Errors: OSTree operation failures
- Permission Errors: Insufficient privileges
- Transaction Errors: Transaction failures
Error Propagation:
// Daemon error handling
void handle_error(const std::string& error, GDBusMethodInvocation* invocation) {
GError* g_error = g_error_new_literal(
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
error.c_str()
);
g_dbus_method_invocation_return_gerror(invocation, g_error);
g_error_free(g_error);
}
// Client error handling
void handle_daemon_error(GError* error) {
std::string error_message = error->message;
std::cerr << "Error: " << error_message << std::endl;
// Provide user guidance based on error type
if (g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
std::cerr << "Daemon is not running. Please start the rpm-ostreed service." << std::endl;
}
}
Security Model
Privilege Separation
Principle: Separate privileged operations from unprivileged user operations
Implementation:
- Daemon: Runs with elevated privileges (root)
- Client: Runs with user privileges
- D-Bus: Secure communication channel
- PolicyKit: Authentication for privileged operations
Authentication
PolicyKit Integration:
<policyconfig>
<action id="org.projectatomic.rpmostree1.upgrade">
<description>Upgrade system</description>
<message>Authentication is required to upgrade the system</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/libexec/rpm-ostreed</annotate>
</action>
</policyconfig>
Sandboxing
Package Script Execution:
- Execute package scripts in controlled environment
- Use namespace isolation for security
- Restrict filesystem access
- Limit privilege escalation
Concurrent Operations
Multiple Clients
Support: Multiple clients can interact with daemon simultaneously
Implementation:
- Thread-Safe Operations: All operations are thread-safe
- Transaction Isolation: Each operation gets its own transaction
- Resource Locking: Prevent conflicting operations
- Queue Management: Queue operations when necessary
Operation Queuing
Queue Management:
class OperationQueue {
std::queue<Operation> pending_operations;
std::mutex queue_mutex;
std::condition_variable queue_cv;
void enqueue_operation(const Operation& operation);
Operation dequeue_operation();
bool has_pending_operations();
};
Performance Optimization
Resource Management
Memory Management:
- Efficient memory usage for large operations
- Garbage collection for completed transactions
- Memory pooling for frequently allocated objects
Disk Management:
- OSTree deduplication for storage efficiency
- Temporary file cleanup
- Cache management for package downloads
Network Optimization:
- Parallel package downloads
- Connection pooling
- Bandwidth optimization
Caching
Package Cache:
- Cache downloaded packages
- Cache package metadata
- Cache dependency resolution results
State Cache:
- Cache deployment information
- Cache package lists
- Cache configuration data
Monitoring and Logging
Logging
Log Levels:
- DEBUG: Detailed debugging information
- INFO: General information
- WARNING: Warning messages
- ERROR: Error messages
- CRITICAL: Critical errors
Log Implementation:
class Logger {
void debug(const std::string& message);
void info(const std::string& message);
void warning(const std::string& message);
void error(const std::string& message);
void critical(const std::string& message);
};
Monitoring
Health Monitoring:
- Daemon health checks
- Transaction monitoring
- Resource usage monitoring
- Error rate monitoring
Metrics Collection:
- Operation success rates
- Performance metrics
- Resource usage statistics
- Error statistics
Systemd Integration
Service Definition
Service File: /usr/lib/systemd/system/rpm-ostreed.service
[Unit]
Description=rpm-ostree Daemon
Documentation=man:rpm-ostreed(8)
After=network.target
[Service]
Type=dbus
BusName=org.projectatomic.rpmostree1
ExecStart=/usr/libexec/rpm-ostreed
Restart=on-failure
RestartSec=1
User=root
Group=root
[Install]
WantedBy=multi-user.target
Also=rpm-ostreed.socket
D-Bus Activation
Socket File: /usr/lib/systemd/system/rpm-ostreed.socket
[Unit]
Description=rpm-ostree D-Bus Socket
Documentation=man:rpm-ostreed(8)
[Socket]
ListenStream=/run/dbus/system_bus_socket
SocketUser=root
SocketGroup=root
[Install]
WantedBy=sockets.target
Error Recovery
Automatic Recovery
Transaction Rollback:
- Automatic rollback on transaction failure
- State restoration to previous known good state
- Resource cleanup after rollback
Daemon Recovery:
- Automatic daemon restart on failure
- State recovery on daemon restart
- Transaction recovery for incomplete operations
Manual Recovery
Recovery Procedures:
- Manual rollback procedures
- State reset procedures
- Configuration recovery procedures
- Filesystem recovery procedures
Future Enhancements
Planned Features
- Container Integration: Direct container support
- Cloud Integration: Cloud deployment support
- Advanced Monitoring: Enhanced monitoring capabilities
- Performance Optimization: Further performance improvements
Architecture Improvements
- Microservices: Split daemon into microservices
- API Gateway: REST API gateway for external access
- Event Streaming: Event streaming for real-time updates
- Distributed Operations: Support for distributed operations