apt-ostree/.notes/dbus/rpm-ostree.md
robojerk d295f9bb4d Major milestone: Complete apt-ostree bootc compatibility and OCI integration
-  Real package installation (replaced mock installation)
-  Real OSTree commit creation from installed packages
-  OCI image creation from both commits and rootfs
-  Full bootc compatibility with proper labels
-  Comprehensive test suite (test-bootc-apt-ostree.sh)
-  Container tool validation (skopeo, podman)
-  Updated compatibility reports for Ubuntu Questing
-  Fixed OCI schema version and field naming issues
-  Temporary directory lifecycle fixes
-  Serde rename attributes for OCI JSON compliance

Ready for Aurora-style workflow deployment!
2025-07-20 21:06:44 +00:00

20 KiB

rpm-ostree D-Bus Interface

Executive Summary

rpm-ostree uses D-Bus as its primary inter-process communication mechanism, providing a standardized interface for client-daemon communication. The D-Bus interface enables secure, reliable communication between unprivileged clients and the privileged daemon.

D-Bus Architecture

Service Overview

Service Name: org.projectatomic.rpmostree1

Purpose: Provide system management interface for rpm-ostree operations

Architecture:

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   CLI Client    │    │   GUI Client    │    │   API Client    │
│  (rpmostree)    │    │  (GNOME/KDE)    │    │  (Python/Go)   │
└─────────┬───────┘    └─────────┬───────┘    └─────────┬───────┘
          │                      │                      │
          └──────────────────────┼──────────────────────┘
                                 │
                    ┌─────────────▼─────────────┐
                    │      D-Bus Interface      │
                    │  (org.projectatomic.rpmo  │
                    │      stree1)              │
                    └─────────────┬─────────────┘
                                  │
                    ┌─────────────▼─────────────┐
                    │    rpm-ostreed Daemon     │
                    │   (Privileged Service)    │
                    └───────────────────────────┘

Design Principles

  1. Standard Interface: Use standard D-Bus conventions and patterns
  2. Type Safety: Strong typing for all method parameters and return values
  3. Error Handling: Comprehensive error reporting and propagation
  4. Progress Reporting: Real-time progress updates via signals
  5. Transaction Management: Transaction-based operations with rollback support

Interface Definition

Main Objects

/org/projectatomic/rpmostree1/Sysroot

Purpose: System root management and deployment operations

Interface: org.projectatomic.rpmostree1.Sysroot

/org/projectatomic/rpmostree1/OS

Purpose: Operating system operations and package management

Interface: org.projectatomic.rpmostree1.OS

Interface XML Definition

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
  <interface name="org.projectatomic.rpmostree1.Sysroot">
    <method name="GetDeployments">
      <arg name="deployments" type="a(sa{sv})" direction="out"/>
    </method>
    
    <method name="GetBootedDeployment">
      <arg name="deployment" type="(sa{sv})" direction="out"/>
    </method>
    
    <method name="GetPendingDeployment">
      <arg name="deployment" type="(sa{sv})" direction="out"/>
    </method>
    
    <method name="GetDeploymentState">
      <arg name="deployment" type="s" direction="in"/>
      <arg name="state" type="s" direction="out"/>
    </method>
  </interface>
  
  <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>
    
    <method name="GetStatus">
      <arg name="status" type="s" direction="out"/>
    </method>
    
    <method name="GetPackages">
      <arg name="packages" type="as" direction="out"/>
    </method>
    
    <method name="SearchPackages">
      <arg name="query" type="s" direction="in"/>
      <arg name="results" type="as" direction="out"/>
    </method>
    
    <method name="GetPackageInfo">
      <arg name="package" type="s" direction="in"/>
      <arg name="info" type="s" direction="out"/>
    </method>
    
    <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>
    
    <signal name="StatusChanged">
      <arg name="status" type="s"/>
    </signal>
  </interface>
</node>

Method Details

Sysroot Methods

GetDeployments

Purpose: Get list of available deployments

Parameters: None

Returns: Array of deployment information

Example:

// Client call
GVariant* result = g_dbus_connection_call_sync(
    connection,
    "org.projectatomic.rpmostree1",
    "/org/projectatomic/rpmostree1/Sysroot",
    "org.projectatomic.rpmostree1.Sysroot",
    "GetDeployments",
    nullptr,
    nullptr,
    G_DBUS_CALL_FLAGS_NONE,
    -1,
    nullptr,
    nullptr
);

// Parse result
GVariantIter* iter;
g_variant_get(result, "(a(sa{sv}))", &iter);

GetBootedDeployment

Purpose: Get information about the currently booted deployment

Parameters: None

Returns: Deployment information for booted deployment

Example:

GVariant* result = g_dbus_connection_call_sync(
    connection,
    "org.projectatomic.rpmostree1",
    "/org/projectatomic/rpmostree1/Sysroot",
    "org.projectatomic.rpmostree1.Sysroot",
    "GetBootedDeployment",
    nullptr,
    nullptr,
    G_DBUS_CALL_FLAGS_NONE,
    -1,
    nullptr,
    nullptr
);

GetPendingDeployment

Purpose: Get information about the pending deployment

Parameters: None

Returns: Deployment information for pending deployment

OS Methods

Upgrade

Purpose: Upgrade system to latest version

Parameters:

  • options: Dictionary of upgrade options

Options:

  • reboot: Boolean - Automatically reboot after upgrade
  • download-only: Boolean - Download updates without installing
  • allow-downgrade: Boolean - Allow downgrading packages
  • unchanged-exit-77: Boolean - Exit with 77 if no changes

Returns: Transaction address for tracking operation

Example:

// Prepare options
GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add(builder, "{sv}", "reboot", g_variant_new_boolean(TRUE));
g_variant_builder_add(builder, "{sv}", "download-only", g_variant_new_boolean(FALSE));

GVariant* options = g_variant_builder_end(builder);

// Call method
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
);

// Get transaction address
const char* transaction_address;
g_variant_get(result, "(s)", &transaction_address);

Rollback

Purpose: Rollback to previous deployment

Parameters:

  • options: Dictionary of rollback options

Options:

  • reboot: Boolean - Automatically reboot after rollback
  • not-as-default: Boolean - Don't set as default boot option

Returns: Transaction address for tracking operation

Deploy

Purpose: Deploy specific version or commit

Parameters:

  • ref: Deployment reference (version or commit hash)
  • options: Dictionary of deployment options

Options:

  • reboot: Boolean - Automatically reboot after deployment
  • not-as-default: Boolean - Don't set as default boot option
  • os: String - Specify operating system name

Returns: Transaction address for tracking operation

Rebase

Purpose: Switch to different base image

Parameters:

  • ref: Base image reference
  • options: Dictionary of rebase options

Options:

  • reboot: Boolean - Automatically reboot after rebase
  • os: String - Specify operating system name

Returns: Transaction address for tracking operation

PkgChange

Purpose: Install or remove packages

Parameters:

  • packages: Array of package names
  • change_type: Type of change ("install" or "remove")
  • options: Dictionary of package change options

Options:

  • reboot: Boolean - Automatically reboot after package change
  • allow-inactive: Boolean - Allow installing on inactive deployment
  • idempotent: Boolean - Don't error if packages already installed/removed

Returns: Transaction address for tracking operation

Example:

// Prepare packages array
GVariantBuilder* packages_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
g_variant_builder_add(packages_builder, "s", "vim");
g_variant_builder_add(packages_builder, "s", "git");

GVariant* packages = g_variant_builder_end(packages_builder);

// Prepare options
GVariantBuilder* options_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add(options_builder, "{sv}", "reboot", g_variant_new_boolean(FALSE));

GVariant* options = g_variant_builder_end(options_builder);

// Call method
GVariant* result = g_dbus_connection_call_sync(
    connection,
    "org.projectatomic.rpmostree1",
    "/org/projectatomic/rpmostree1/OS",
    "org.projectatomic.rpmostree1.OS",
    "PkgChange",
    g_variant_new("(assa{sv})", packages, "install", options),
    nullptr,
    G_DBUS_CALL_FLAGS_NONE,
    -1,
    nullptr,
    nullptr
);

KernelArgs

Purpose: Manage kernel arguments

Parameters:

  • operation: Operation type ("append", "delete", "replace", "show")
  • args: Array of kernel arguments
  • options: Dictionary of kernel argument options

Options:

  • reboot: Boolean - Automatically reboot after changes

Returns: Transaction address for tracking operation

Cleanup

Purpose: Clean up old deployments

Parameters:

  • options: Dictionary of cleanup options

Options:

  • base: Boolean - Clean up base images
  • repomd: Boolean - Clean up repository metadata
  • rollback: Boolean - Clean up rollback deployments

Returns: Transaction address for tracking operation

GetStatus

Purpose: Get system status

Parameters: None

Returns: JSON-formatted status string

Example:

GVariant* result = g_dbus_connection_call_sync(
    connection,
    "org.projectatomic.rpmostree1",
    "/org/projectatomic/rpmostree1/OS",
    "org.projectatomic.rpmostree1.OS",
    "GetStatus",
    nullptr,
    nullptr,
    G_DBUS_CALL_FLAGS_NONE,
    -1,
    nullptr,
    nullptr
);

const char* status;
g_variant_get(result, "(s)", &status);
printf("Status: %s\n", status);

GetPackages

Purpose: Get list of installed packages

Parameters: None

Returns: Array of package names

SearchPackages

Purpose: Search for packages

Parameters:

  • query: Search query string

Returns: Array of matching package names

GetPackageInfo

Purpose: Get detailed package information

Parameters:

  • package: Package name

Returns: JSON-formatted package information

Signals

TransactionChanged

Purpose: Report transaction state changes

Parameters:

  • transaction_address: Transaction identifier
  • state: Transaction state ("preparing", "downloading", "installing", "finalizing")
  • message: Human-readable status message
  • percentage: Progress percentage (0-100)

Example:

// Signal handler
void handle_transaction_changed(GDBusConnection* connection,
                               const char* sender,
                               const char* object_path,
                               const char* interface_name,
                               const char* signal_name,
                               GVariant* parameters,
                               void* user_data) {
    const char* transaction_address;
    const char* state;
    const char* message;
    int percentage;
    
    g_variant_get(parameters, "(sssi)", &transaction_address, &state, &message, &percentage);
    
    printf("Transaction %s: %s - %s (%d%%)\n", 
           transaction_address, state, message, percentage);
}

TransactionCompleted

Purpose: Report transaction completion

Parameters:

  • transaction_address: Transaction identifier
  • success: Boolean indicating success or failure
  • result: Result message or error description

Example:

void handle_transaction_completed(GDBusConnection* connection,
                                 const char* sender,
                                 const char* object_path,
                                 const char* interface_name,
                                 const char* signal_name,
                                 GVariant* parameters,
                                 void* user_data) {
    const char* transaction_address;
    gboolean success;
    const char* result;
    
    g_variant_get(parameters, "(sbs)", &transaction_address, &success, &result);
    
    if (success) {
        printf("Transaction %s completed successfully: %s\n", transaction_address, result);
    } else {
        printf("Transaction %s failed: %s\n", transaction_address, result);
    }
}

StatusChanged

Purpose: Report system status changes

Parameters:

  • status: New system status

Transaction Management

Transaction Lifecycle

  1. Initiation: Client calls method, receives transaction address
  2. Progress: Daemon emits TransactionChanged signals
  3. Completion: Daemon emits TransactionCompleted signal
  4. Cleanup: Transaction resources are cleaned up

Transaction States

  • preparing: Transaction is being prepared
  • downloading: Packages are being downloaded
  • installing: Packages are being installed
  • finalizing: Transaction is being finalized
  • completed: Transaction completed successfully
  • failed: Transaction failed

Transaction Tracking

Example:

// Start transaction
const char* transaction_address;
g_variant_get(result, "(s)", &transaction_address);

// Subscribe to transaction signals
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
);

g_dbus_connection_signal_subscribe(
    connection,
    "org.projectatomic.rpmostree1",
    "org.projectatomic.rpmostree1.OS",
    "TransactionCompleted",
    "/org/projectatomic/rpmostree1/OS",
    nullptr,
    G_DBUS_SIGNAL_FLAGS_NONE,
    handle_transaction_completed,
    nullptr,
    nullptr
);

Error Handling

Error Types

  1. G_DBUS_ERROR_SERVICE_UNKNOWN: Daemon service not available
  2. G_DBUS_ERROR_NO_REPLY: Daemon not responding
  3. G_DBUS_ERROR_TIMEOUT: Operation timed out
  4. G_DBUS_ERROR_FAILED: General operation failure
  5. G_DBUS_ERROR_INVALID_ARGS: Invalid method arguments

Error Handling Example

GError* error = nullptr;
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,
    &error
);

if (error != nullptr) {
    if (g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
        fprintf(stderr, "Daemon is not running. Please start the rpm-ostreed service.\n");
    } else if (g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_NO_REPLY)) {
        fprintf(stderr, "Daemon is not responding. Please check the service status.\n");
    } else {
        fprintf(stderr, "Error: %s\n", error->message);
    }
    g_error_free(error);
}

Security

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>
    
    <action id="org.projectatomic.rpmostree1.install">
        <description>Install packages</description>
        <message>Authentication is required to install packages</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>

Access Control

  • System Bus: D-Bus system bus for privileged operations
  • Service Activation: Automatic service activation via systemd
  • User Permissions: PolicyKit-based user permission management

Performance Considerations

Connection Management

Connection Pooling:

// Reuse connections when possible
static GDBusConnection* get_connection() {
    static GDBusConnection* connection = nullptr;
    if (connection == nullptr) {
        connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, nullptr);
    }
    return connection;
}

Async Operations

Non-blocking Calls:

g_dbus_connection_call(
    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,
    handle_upgrade_response,
    nullptr
);

Monitoring and Debugging

D-Bus Monitoring

Monitor D-Bus Traffic:

# Monitor all D-Bus traffic
dbus-monitor --system

# Monitor specific service
dbus-monitor --system "destination='org.projectatomic.rpmostree1'"

Debugging Tools

D-Bus Introspection:

# Introspect service
gdbus introspect --system --dest org.projectatomic.rpmostree1 --object-path /org/projectatomic/rpmostree1/OS

D-Bus Call Testing:

# Test method call
gdbus call --system --dest org.projectatomic.rpmostree1 --object-path /org/projectatomic/rpmostree1/OS --method org.projectatomic.rpmostree1.OS.GetStatus

Future Enhancements

Planned Features

  1. Event Streaming: Real-time event streaming for status updates
  2. Batch Operations: Support for batch operations
  3. Advanced Filtering: Enhanced filtering and querying capabilities
  4. Performance Optimization: Further performance improvements

Interface Improvements

  1. Versioning: Interface versioning for backward compatibility
  2. Extensions: Extensible interface for custom operations
  3. Validation: Enhanced parameter validation
  4. Documentation: Improved interface documentation