apt-ostree/docs/apt-ostree-daemon-plan/3rd-party-integration.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

19 KiB

rpm-ostree Third-Party Tools Integration

Overview

rpm-ostree integrates with various third-party tools and external systems to provide comprehensive system management capabilities. This document explains how rpm-ostree implements integration with these tools.

Core Third-Party Dependencies

libdnf Integration

rpm-ostree uses libdnf for RPM package management:

// libdnf integration in rpmostree-core.cxx
#include <dnf/dnf-context.h>
#include <dnf/dnf-goal.h>
#include <dnf/dnf-package.h>

class RpmOstreeDnfIntegration {
private:
    DnfContext *dnf_context;
    DnfGoal *dnf_goal;
    
public:
    // Initialize DNF context for OSTree operations
    gboolean initialize_dnf_context(
        RpmOstreeSysroot *sysroot,
        const char *deployment_path,
        GCancellable *cancellable,
        GError **error) {
        
        // Create DNF context
        dnf_context = dnf_context_new();
        
        // Configure for OSTree deployment
        dnf_context_set_install_root(dnf_context, deployment_path);
        dnf_context_set_release_ver(dnf_context, "39");
        dnf_context_set_platform_module(dnf_context, "platform:39");
        
        // Load repositories
        dnf_context_setup(dnf_context, cancellable, error);
        
        return TRUE;
    }
    
    // Resolve package dependencies
    gboolean resolve_package_dependencies(
        const char *package_name,
        GPtrArray **resolved_packages,
        GCancellable *cancellable,
        GError **error) {
        
        // Create DNF goal
        dnf_goal = dnf_goal_new(dnf_context);
        
        // Add package to goal
        dnf_goal_install(dnf_goal, package_name);
        
        // Resolve dependencies
        DnfGoalActions actions = dnf_goal_resolve(dnf_goal, error);
        if (actions == DNF_GOAL_ACTION_ERROR) {
            return FALSE;
        }
        
        // Get resolved packages
        GPtrArray *packages = dnf_goal_get_packages(dnf_goal, DNF_PACKAGE_INFO_INSTALL);
        *resolved_packages = packages;
        
        return TRUE;
    }
    
    // Download packages
    gboolean download_packages(
        GPtrArray *packages,
        const char *download_path,
        GCancellable *cancellable,
        GError **error) {
        
        // Download packages to specified path
        return dnf_context_download_packages(
            dnf_context, packages, download_path, cancellable, error);
    }
};

Bubblewrap Integration

rpm-ostree uses bubblewrap for secure package script execution:

// Bubblewrap integration in rpmostree-core.cxx
#include <bwrap.h>

class RpmOstreeBubblewrap {
public:
    // Execute package scripts in sandboxed environment
    gboolean execute_package_script(
        const char *script_path,
        const char *deployment_path,
        const char *package_name,
        GCancellable *cancellable,
        GError **error) {
        
        // Create bubblewrap arguments
        g_autoptr(GPtrArray) args = g_ptr_array_new();
        g_ptr_array_add(args, (gpointer)"bwrap");
        g_ptr_array_add(args, (gpointer)"--dev-bind");
        g_ptr_array_add(args, (gpointer)"/dev");
        g_ptr_array_add(args, (gpointer)"/dev");
        g_ptr_array_add(args, (gpointer)"--proc");
        g_ptr_array_add(args, (gpointer)"/proc");
        g_ptr_array_add(args, (gpointer)"--bind");
        g_ptr_array_add(args, (gpointer)deployment_path);
        g_ptr_array_add(args, (gpointer)"/");
        g_ptr_array_add(args, (gpointer)"--chdir");
        g_ptr_array_add(args, (gpointer)"/");
        g_ptr_array_add(args, (gpointer)script_path);
        g_ptr_array_add(args, NULL);
        
        // Execute script in sandbox
        return rpmostree_sysroot_run_sync(
            sysroot, (char**)args->pdata, cancellable, error);
    }
    
    // Execute post-installation scripts
    gboolean execute_postinstall_scripts(
        const char *deployment_path,
        GPtrArray *packages,
        GCancellable *cancellable,
        GError **error) {
        
        // Execute post-installation scripts for each package
        for (guint i = 0; i < packages->len; i++) {
            DnfPackage *package = g_ptr_array_index(packages, i);
            const char *package_name = dnf_package_get_name(package);
            
            // Find and execute post-installation script
            g_autofree char *script_path = g_strdup_printf(
                "%s/var/lib/rpm-postinst/%s", deployment_path, package_name);
            
            if (g_file_test(script_path, G_FILE_TEST_EXISTS)) {
                execute_package_script(script_path, deployment_path, package_name, cancellable, error);
            }
        }
        
        return TRUE;
    }
};

systemd Integration

rpm-ostree integrates with systemd for service management:

// systemd integration in rpmostreed-daemon.cxx
#include <systemd/sd-bus.h>
#include <systemd/sd-daemon.h>

class RpmOstreeSystemdIntegration {
private:
    sd_bus *system_bus;
    
public:
    // Initialize systemd integration
    gboolean initialize_systemd_integration(GError **error) {
        // Connect to system bus
        int ret = sd_bus_open_system(&system_bus);
        if (ret < 0) {
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to connect to system bus: %s", strerror(-ret));
            return FALSE;
        }
        
        return TRUE;
    }
    
    // Reload systemd units after package installation
    gboolean reload_systemd_units(
        GPtrArray *installed_packages,
        GCancellable *cancellable,
        GError **error) {
        
        // Reload systemd daemon
        sd_bus_message *reply = NULL;
        int ret = sd_bus_call_method(system_bus,
                                   "org.freedesktop.systemd1",
                                   "/org/freedesktop/systemd1",
                                   "org.freedesktop.systemd1.Manager",
                                   "Reload",
                                   NULL, &reply, NULL);
        
        if (ret < 0) {
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to reload systemd: %s", strerror(-ret));
            return FALSE;
        }
        
        sd_bus_message_unref(reply);
        return TRUE;
    }
    
    // Enable/disable systemd services
    gboolean manage_systemd_services(
        GPtrArray *services,
        gboolean enable,
        GCancellable *cancellable,
        GError **error) {
        
        for (guint i = 0; i < services->len; i++) {
            const char *service = g_ptr_array_index(services, i);
            
            // Enable or disable service
            const char *method = enable ? "EnableUnitFiles" : "DisableUnitFiles";
            sd_bus_message *reply = NULL;
            int ret = sd_bus_call_method(system_bus,
                                       "org.freedesktop.systemd1",
                                       "/org/freedesktop/systemd1",
                                       "org.freedesktop.systemd1.Manager",
                                       method,
                                       NULL, &reply, "as", 1, &service);
            
            if (ret < 0) {
                g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "Failed to %s service %s: %s",
                           enable ? "enable" : "disable", service, strerror(-ret));
                return FALSE;
            }
            
            sd_bus_message_unref(reply);
        }
        
        return TRUE;
    }
};

External Tool Integration

PolicyKit Integration

rpm-ostree uses PolicyKit for authentication:

// PolicyKit integration in rpmostreed-daemon.cxx
#include <polkit/polkit.h>

class RpmOstreePolicyKit {
private:
    PolkitAuthority *authority;
    
public:
    // Initialize PolicyKit integration
    gboolean initialize_polkit(GError **error) {
        authority = polkit_authority_get_sync(NULL, error);
        if (!authority) {
            return FALSE;
        }
        return TRUE;
    }
    
    // Check if user has required privileges
    gboolean check_privileges(
        const char *action_id,
        const char *subject,
        GCancellable *cancellable,
        GError **error) {
        
        // Create subject for authentication
        PolkitSubject *polkit_subject = polkit_system_bus_name_new(subject);
        
        // Check authorization
        PolkitAuthorizationResult *result = polkit_authority_check_authorization_sync(
            authority, polkit_subject, action_id, NULL,
            POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
            cancellable, error);
        
        if (!result) {
            return FALSE;
        }
        
        gboolean authorized = polkit_authorization_result_get_is_authorized(result);
        polkit_authorization_result_unref(result);
        polkit_subject_unref(polkit_subject);
        
        return authorized;
    }
    
    // Required action IDs for rpm-ostree operations
    static const char *REQUIRED_ACTIONS[] = {
        "org.projectatomic.rpmostree1.upgrade",
        "org.projectatomic.rpmostree1.rollback",
        "org.projectatomic.rpmostree1.deploy",
        "org.projectatomic.rpmostree1.rebase",
        "org.projectatomic.rpmostree1.pkg-change",
        NULL
    };
};

SELinux Integration

rpm-ostree integrates with SELinux for security policy management:

// SELinux integration in rpmostree-core.cxx
#include <selinux/selinux.h>
#include <selinux/label.h>

class RpmOstreeSELinux {
public:
    // Apply SELinux labels to deployment
    gboolean apply_selinux_labels(
        const char *deployment_path,
        GCancellable *cancellable,
        GError **error) {
        
        // Initialize SELinux labeling
        struct selabel_handle *handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
        if (!handle) {
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to initialize SELinux labeling");
            return FALSE;
        }
        
        // Apply labels recursively
        gboolean success = apply_labels_recursive(deployment_path, handle, error);
        
        selabel_close(handle);
        return success;
    }
    
private:
    // Apply labels recursively to directory tree
    gboolean apply_labels_recursive(
        const char *path,
        struct selabel_handle *handle,
        GError **error) {
        
        // Apply label to current path
        char *con;
        if (selabel_lookup(handle, &con, path, S_IFDIR) == 0) {
            if (setfilecon(path, con) < 0) {
                g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "Failed to set SELinux context on %s", path);
                freecon(con);
                return FALSE;
            }
            freecon(con);
        }
        
        // Recursively process subdirectories
        GDir *dir = g_dir_open(path, 0, error);
        if (!dir) {
            return FALSE;
        }
        
        const char *name;
        while ((name = g_dir_read_name(dir))) {
            g_autofree char *subpath = g_build_filename(path, name, NULL);
            
            if (g_file_test(subpath, G_FILE_TEST_IS_DIR)) {
                if (!apply_labels_recursive(subpath, handle, error)) {
                    g_dir_close(dir);
                    return FALSE;
                }
            }
        }
        
        g_dir_close(dir);
        return TRUE;
    }
};

Development Tools Integration

Git Integration

rpm-ostree uses Git for version control of configuration:

// Git integration in rpmostree-core.cxx
#include <git2.h>

class RpmOstreeGit {
public:
    // Initialize Git repository for configuration tracking
    gboolean initialize_git_repo(
        const char *config_path,
        GCancellable *cancellable,
        GError **error) {
        
        // Initialize Git repository
        git_repository *repo;
        int ret = git_repository_init(&repo, config_path, 0);
        if (ret < 0) {
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to initialize Git repository: %s", git_error_last()->message);
            return FALSE;
        }
        
        git_repository_free(repo);
        return TRUE;
    }
    
    // Commit configuration changes
    gboolean commit_config_changes(
        const char *config_path,
        const char *message,
        GCancellable *cancellable,
        GError **error) {
        
        git_repository *repo;
        int ret = git_repository_open(&repo, config_path);
        if (ret < 0) {
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to open Git repository: %s", git_error_last()->message);
            return FALSE;
        }
        
        // Stage all changes
        git_index *index;
        ret = git_repository_index(&index, repo);
        if (ret < 0) {
            git_repository_free(repo);
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to get repository index: %s", git_error_last()->message);
            return FALSE;
        }
        
        ret = git_index_add_all(index, NULL, 0, NULL, NULL);
        if (ret < 0) {
            git_index_free(index);
            git_repository_free(repo);
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to stage changes: %s", git_error_last()->message);
            return FALSE;
        }
        
        // Create commit
        git_oid tree_id, commit_id;
        ret = git_index_write_tree(&tree_id, index);
        if (ret < 0) {
            git_index_free(index);
            git_repository_free(repo);
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to write tree: %s", git_error_last()->message);
            return FALSE;
        }
        
        git_tree *tree;
        ret = git_tree_lookup(&tree, repo, &tree_id);
        if (ret < 0) {
            git_index_free(index);
            git_repository_free(repo);
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to lookup tree: %s", git_error_last()->message);
            return FALSE;
        }
        
        // Get HEAD commit as parent
        git_oid parent_id;
        git_commit *parent = NULL;
        if (git_reference_name_to_id(&parent_id, repo, "HEAD") == 0) {
            git_commit_lookup(&parent, repo, &parent_id);
        }
        
        // Create commit
        git_signature *signature;
        ret = git_signature_default(&signature, repo);
        if (ret < 0) {
            git_tree_free(tree);
            git_commit_free(parent);
            git_index_free(index);
            git_repository_free(repo);
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to create signature: %s", git_error_last()->message);
            return FALSE;
        }
        
        const git_commit *parents[] = { parent };
        ret = git_commit_create(&commit_id, repo, "HEAD", signature, signature,
                               NULL, message, tree, parent ? 1 : 0, parents);
        
        git_signature_free(signature);
        git_tree_free(tree);
        git_commit_free(parent);
        git_index_free(index);
        git_repository_free(repo);
        
        if (ret < 0) {
            g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Failed to create commit: %s", git_error_last()->message);
            return FALSE;
        }
        
        return TRUE;
    }
};

Testing Tools Integration

Integration Testing

rpm-ostree integrates with various testing tools:

// Testing integration in tests/
class RpmOstreeTesting {
public:
    // Run integration tests
    gboolean run_integration_tests(
        const char *test_suite,
        GCancellable *cancellable,
        GError **error) {
        
        // Run specific test suite
        g_autofree char *test_command = g_strdup_printf(
            "make check TEST_SUITE=%s", test_suite);
        
        return rpmostree_sysroot_run_sync(
            sysroot, test_command, cancellable, error);
    }
    
    // Run unit tests
    gboolean run_unit_tests(
        const char *test_binary,
        GCancellable *cancellable,
        GError **error) {
        
        // Run unit test binary
        g_autofree char *test_command = g_strdup_printf(
            "./%s", test_binary);
        
        return rpmostree_sysroot_run_sync(
            sysroot, test_command, cancellable, error);
    }
    
    // Run performance benchmarks
    gboolean run_performance_benchmarks(
        const char *benchmark_suite,
        GCancellable *cancellable,
        GError **error) {
        
        // Run performance benchmarks
        g_autofree char *benchmark_command = g_strdup_printf(
            "make benchmark BENCHMARK_SUITE=%s", benchmark_suite);
        
        return rpmostree_sysroot_run_sync(
            sysroot, benchmark_command, cancellable, error);
    }
};

Monitoring and Logging Tools

Journald Integration

rpm-ostree integrates with systemd-journald for logging:

// Journald integration in rpmostreed-daemon.cxx
#include <systemd/sd-journal.h>

class RpmOstreeJournald {
public:
    // Log rpm-ostree events to journald
    void log_event(
        const char *event_type,
        const char *message,
        const char *package_name) {
        
        sd_journal_send(
            "MESSAGE=%s", message,
            "EVENT_TYPE=%s", event_type,
            "PACKAGE_NAME=%s", package_name ?: "",
            "SYSLOG_IDENTIFIER=rpm-ostree",
            "PRIORITY=6",  // INFO level
            NULL);
    }
    
    // Log error events
    void log_error(
        const char *error_message,
        const char *operation,
        GError *error) {
        
        sd_journal_send(
            "MESSAGE=%s", error_message,
            "ERROR_DOMAIN=%s", g_quark_to_string(g_error_domain(error)),
            "ERROR_CODE=%d", g_error_code(error),
            "OPERATION=%s", operation,
            "SYSLOG_IDENTIFIER=rpm-ostree",
            "PRIORITY=3",  // ERROR level
            NULL);
    }
    
    // Log transaction events
    void log_transaction(
        const char *transaction_id,
        const char *operation,
        const char *status) {
        
        sd_journal_send(
            "MESSAGE=Transaction %s %s: %s", transaction_id, operation, status,
            "TRANSACTION_ID=%s", transaction_id,
            "OPERATION=%s", operation,
            "STATUS=%s", status,
            "SYSLOG_IDENTIFIER=rpm-ostree",
            "PRIORITY=6",  // INFO level
            NULL);
    }
};

Future Tool Integrations

Planned Integrations

  1. OCI Container Tools: Integration with container tools for image management
  2. Bootc Compatibility: Integration with bootc for container-native deployments
  3. Composefs Integration: Enhanced filesystem layering with composefs
  4. Enhanced Monitoring: Integration with Prometheus and Grafana for metrics

Integration Roadmap

  • Phase 1: Core tool integrations ( Complete)
  • Phase 2: Security tool integrations ( Complete)
  • Phase 3: Monitoring and logging ( Complete)
  • Phase 4: Container tool integrations (🔄 In Progress)
  • Phase 5: Advanced monitoring (📋 Planned)