apt-ostree/docs/apt-ostree-daemon-plan/client-daemon.md
robojerk 306a68b89a fix: Resolve compilation errors in parallel and cache modules
- 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
2025-08-16 15:10:00 -07:00

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

  1. Privilege Separation: Daemon runs with elevated privileges, clients run unprivileged
  2. D-Bus Communication: Standard system service interface for inter-process communication
  3. Transaction Management: Atomic operations with rollback capability
  4. Concurrent Operations: Multiple clients can interact simultaneously
  5. 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:

  1. Parse command-line arguments
  2. Connect to daemon via D-Bus
  3. Send operation request
  4. Handle progress updates
  5. 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:

  1. Initialize system components
  2. Register D-Bus service
  3. Start listening for client connections
  4. Handle client requests
  5. 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:

  1. DeployTransaction: New deployment creation
  2. RollbackTransaction: Deployment rollback
  3. PkgChangeTransaction: Package installation/removal
  4. RebaseTransaction: Base image switching
  5. 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:

  1. Initiation: Client requests operation
  2. Validation: Validate request parameters
  3. Preparation: Set up rollback points
  4. Execution: Perform operation with progress reporting
  5. Completion: Finalize operation or rollback
  6. 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:

  1. Network Errors: Package download failures
  2. Dependency Errors: Package dependency conflicts
  3. Filesystem Errors: OSTree operation failures
  4. Permission Errors: Insufficient privileges
  5. 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

  1. Container Integration: Direct container support
  2. Cloud Integration: Cloud deployment support
  3. Advanced Monitoring: Enhanced monitoring capabilities
  4. Performance Optimization: Further performance improvements

Architecture Improvements

  1. Microservices: Split daemon into microservices
  2. API Gateway: REST API gateway for external access
  3. Event Streaming: Event streaming for real-time updates
  4. Distributed Operations: Support for distributed operations