Initial commit: apt-ostree project with 100% rpm-ostree CLI compatibility
This commit is contained in:
commit
a48ad95d70
81 changed files with 28515 additions and 0 deletions
370
.notes/rpm-ostree/how-commands-work/pkg-install.md
Normal file
370
.notes/rpm-ostree/how-commands-work/pkg-install.md
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
# rpm-ostree install Command Flow Analysis
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides a detailed, step-by-step analysis of what happens when a user runs `rpm-ostree install htop`. The analysis is based on examination of the rpm-ostree source code and reveals the complex orchestration between client-side CLI parsing, D-Bus communication, daemon-side processing, and the underlying OSTree and DNF (libdnf) systems.
|
||||
|
||||
## Command Entry Point
|
||||
|
||||
### 1. CLI Parsing and Validation
|
||||
|
||||
**File**: `src/app/rpmostree-pkg-builtins.cxx`
|
||||
**Function**: `rpmostree_builtin_install()`
|
||||
|
||||
```cpp
|
||||
gboolean
|
||||
rpmostree_builtin_install (int argc, char **argv, RpmOstreeCommandInvocation *invocation,
|
||||
GCancellable *cancellable, GError **error)
|
||||
```
|
||||
|
||||
**Steps**:
|
||||
1. **Option Parsing**: Parse command-line options using GLib's `GOptionContext`
|
||||
- `--reboot`, `--dry-run`, `--apply-live`, `--idempotent`, etc.
|
||||
- Package names are extracted from positional arguments
|
||||
|
||||
2. **Argument Validation**: Ensure at least one package is specified
|
||||
```cpp
|
||||
if (argc < 2) {
|
||||
rpmostree_usage_error (context, "At least one PACKAGE must be specified", error);
|
||||
return FALSE;
|
||||
}
|
||||
```
|
||||
|
||||
3. **Interactive Confirmation**: Handle `--apply-live` without `--assumeyes`
|
||||
- If running interactively, perform a dry-run first and prompt for confirmation
|
||||
- If non-interactive (script), auto-infer `--assumeyes` with a warning
|
||||
|
||||
4. **Container Detection**: Check if running in an OSTree container
|
||||
- If in container, use different code path for container rebuilds
|
||||
- Otherwise, proceed with normal system installation
|
||||
|
||||
### 2. Core Package Change Logic
|
||||
|
||||
**Function**: `pkg_change()`
|
||||
|
||||
**Steps**:
|
||||
1. **Package Classification**: Determine package types
|
||||
```cpp
|
||||
gboolean met_local_pkg = FALSE;
|
||||
for (const char *const *it = packages_to_add; it && *it; it++)
|
||||
met_local_pkg = met_local_pkg || g_str_has_suffix (*it, ".rpm") || g_str_has_prefix (*it, "file://");
|
||||
```
|
||||
|
||||
2. **Option Dictionary Creation**: Build GVariant dictionary with all options
|
||||
```cpp
|
||||
GVariantDict dict;
|
||||
g_variant_dict_init (&dict, NULL);
|
||||
g_variant_dict_insert (&dict, "reboot", "b", opt_reboot);
|
||||
g_variant_dict_insert (&dict, "cache-only", "b", opt_cache_only);
|
||||
g_variant_dict_insert (&dict, "download-only", "b", opt_download_only);
|
||||
// ... more options
|
||||
```
|
||||
|
||||
3. **API Selection**: Choose between legacy and new D-Bus APIs
|
||||
- **Legacy API**: `rpmostree_os_call_pkg_change_sync()` for simple cases
|
||||
- **New API**: `rpmostree_update_deployment()` for complex cases (local packages, apply-live, etc.)
|
||||
|
||||
## D-Bus Communication Layer
|
||||
|
||||
### 3. Client-Side D-Bus Setup
|
||||
|
||||
**File**: `src/app/rpmostree-clientlib.cxx`
|
||||
|
||||
**Steps**:
|
||||
1. **Daemon Startup**: Ensure rpm-ostreed daemon is running
|
||||
```cpp
|
||||
ROSCXX_TRY (client_start_daemon (), error);
|
||||
```
|
||||
|
||||
2. **System Bus Connection**: Connect to system D-Bus
|
||||
```cpp
|
||||
g_autoptr (GDBusConnection) connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error);
|
||||
```
|
||||
|
||||
3. **Client Registration**: Register as a client with the daemon
|
||||
```cpp
|
||||
g_dbus_connection_call_sync (connection, bus_name, sysroot_objpath,
|
||||
"org.projectatomic.rpmostree1.Sysroot", "RegisterClient", ...);
|
||||
```
|
||||
|
||||
4. **OS Proxy Creation**: Get proxy to the OS interface
|
||||
```cpp
|
||||
glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
|
||||
if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname, cancellable, &os_proxy, error))
|
||||
return FALSE;
|
||||
```
|
||||
|
||||
### 4. D-Bus Method Invocation
|
||||
|
||||
**Legacy API Path** (`rpmostree_os_call_pkg_change_sync`):
|
||||
```cpp
|
||||
if (!rpmostree_os_call_pkg_change_sync (os_proxy, options, install_pkgs, uninstall_pkgs, NULL,
|
||||
&transaction_address, NULL, cancellable, error))
|
||||
return FALSE;
|
||||
```
|
||||
|
||||
**New API Path** (`rpmostree_update_deployment`):
|
||||
```cpp
|
||||
if (!rpmostree_update_deployment (os_proxy, NULL, /* refspec */
|
||||
NULL, /* revision */
|
||||
install_pkgs, install_fileoverride_pkgs, uninstall_pkgs,
|
||||
NULL, /* override replace */
|
||||
NULL, /* override remove */
|
||||
NULL, /* override reset */
|
||||
NULL, /* local_repo_remote */
|
||||
NULL, /* treefile */
|
||||
options, &transaction_address, cancellable, error))
|
||||
return FALSE;
|
||||
```
|
||||
|
||||
## Daemon-Side Processing
|
||||
|
||||
### 5. D-Bus Method Handler
|
||||
|
||||
**File**: `src/daemon/rpmostreed-os.cxx`
|
||||
|
||||
**Steps**:
|
||||
1. **Authorization Check**: Verify user permissions via Polkit
|
||||
```cpp
|
||||
else if (g_strcmp0 (method_name, "PkgChange") == 0) {
|
||||
g_ptr_array_add (actions, (void *)"org.projectatomic.rpmostree1.install-uninstall-packages");
|
||||
}
|
||||
```
|
||||
|
||||
2. **Transaction Management**: Check for existing transactions or create new one
|
||||
```cpp
|
||||
if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error))
|
||||
return os_throw_dbus_invocation_error (invocation, &local_error);
|
||||
```
|
||||
|
||||
3. **Transaction Creation**: Create appropriate transaction type
|
||||
- For package changes: `rpmostreed_transaction_new_pkg_change()`
|
||||
- For deployment updates: `rpmostreed_transaction_new_update_deployment()`
|
||||
|
||||
4. **Transaction Address Return**: Return D-Bus object path for transaction monitoring
|
||||
```cpp
|
||||
const char *client_address = rpmostreed_transaction_get_client_address (transaction);
|
||||
rpmostree_os_complete_pkg_change (interface, invocation, client_address);
|
||||
```
|
||||
|
||||
### 6. Transaction Processing
|
||||
|
||||
**File**: `src/daemon/rpmostreed-transaction.cxx`
|
||||
|
||||
**Steps**:
|
||||
1. **Transaction State Management**: Track transaction progress and state
|
||||
2. **Dependency Resolution**: Use libdnf to resolve package dependencies
|
||||
3. **Package Download**: Download required RPM packages from repositories
|
||||
4. **OSTree Integration**: Prepare for OSTree commit creation
|
||||
|
||||
## Core Package Management
|
||||
|
||||
### 7. DNF Integration (libdnf)
|
||||
|
||||
**Steps**:
|
||||
1. **Repository Setup**: Initialize DNF context with configured repositories
|
||||
```cpp
|
||||
g_autoptr (DnfContext) dnfctx = dnf_context_new ();
|
||||
```
|
||||
|
||||
2. **Package Resolution**: Resolve package names to specific RPM packages
|
||||
```cpp
|
||||
hy_autoquery HyQuery query = hy_query_create (dnf_context_get_sack (dnfctx));
|
||||
hy_query_filter (query, HY_PKG_NAME, HY_EQ, package_name);
|
||||
```
|
||||
|
||||
3. **Dependency Resolution**: Calculate full dependency tree
|
||||
- Resolve all required dependencies
|
||||
- Handle conflicts and alternatives
|
||||
- Determine download order
|
||||
|
||||
4. **Package Download**: Download RPM files to local cache
|
||||
- Use DNF's download infrastructure
|
||||
- Verify package integrity
|
||||
- Handle network failures and retries
|
||||
|
||||
### 8. OSTree Integration
|
||||
|
||||
**Steps**:
|
||||
1. **Base Tree Preparation**: Get current OSTree deployment as base
|
||||
```cpp
|
||||
OstreeDeployment *booted = ostree_sysroot_get_booted_deployment (sysroot);
|
||||
```
|
||||
|
||||
2. **Package Import**: Import downloaded RPMs into OSTree repository
|
||||
- Extract RPM contents
|
||||
- Apply to filesystem tree
|
||||
- Handle file conflicts and replacements
|
||||
|
||||
3. **Commit Creation**: Create new OSTree commit with layered packages
|
||||
```cpp
|
||||
// Create new commit with package changes
|
||||
ostree_repo_prepare_transaction (repo, NULL, NULL, error);
|
||||
// ... package application logic ...
|
||||
ostree_repo_commit_transaction (repo, NULL, error);
|
||||
```
|
||||
|
||||
4. **Metadata Generation**: Generate commit metadata
|
||||
- Package lists and versions
|
||||
- Dependency information
|
||||
- Origin and timestamp data
|
||||
|
||||
## Filesystem and Deployment
|
||||
|
||||
### 9. Filesystem Assembly
|
||||
|
||||
**Steps**:
|
||||
1. **Base Tree Checkout**: Checkout base OSTree commit to temporary location
|
||||
2. **Package Application**: Apply RPM contents to filesystem
|
||||
- Extract files from RPMs
|
||||
- Handle file permissions and ownership
|
||||
- Apply package scripts (preinst, postinst)
|
||||
|
||||
3. **Layer Management**: Create layered filesystem structure
|
||||
- `/usr` - Base system files (immutable)
|
||||
- `/var` - Variable data (mutable)
|
||||
- `/etc` - Configuration (merged)
|
||||
- Package overlays in `/usr/lib/rpm-ostree/`
|
||||
|
||||
4. **Script Execution**: Run package installation scripts
|
||||
- Pre-installation scripts
|
||||
- Post-installation scripts
|
||||
- Handle script failures and rollback
|
||||
|
||||
### 10. Deployment Management
|
||||
|
||||
**Steps**:
|
||||
1. **Deployment Creation**: Create new OSTree deployment
|
||||
```cpp
|
||||
ostree_sysroot_deploy_tree (sysroot, osname, new_commit, ...);
|
||||
```
|
||||
|
||||
2. **Boot Configuration**: Update bootloader configuration
|
||||
- Generate new initramfs if needed
|
||||
- Update kernel arguments
|
||||
- Configure boot entries
|
||||
|
||||
3. **State Persistence**: Save deployment state
|
||||
- Update deployment index
|
||||
- Save package metadata
|
||||
- Update rollback information
|
||||
|
||||
## Transaction Monitoring
|
||||
|
||||
### 11. Progress Reporting
|
||||
|
||||
**Steps**:
|
||||
1. **Signal Emission**: Emit D-Bus signals for progress
|
||||
```cpp
|
||||
// Progress signals
|
||||
rpmostree_transaction_emit_percent_progress (transaction, "Downloading packages", 50);
|
||||
rpmostree_transaction_emit_message (transaction, "Installing htop-2.2.0-1.fc33.x86_64");
|
||||
```
|
||||
|
||||
2. **Client Monitoring**: Client receives and displays progress
|
||||
```cpp
|
||||
// Client connects to transaction and monitors signals
|
||||
rpmostree_transaction_client_run (invocation, sysroot_proxy, os_proxy, options, ...);
|
||||
```
|
||||
|
||||
3. **Error Handling**: Handle failures and provide rollback
|
||||
- Network failures during download
|
||||
- Package conflicts
|
||||
- Script execution failures
|
||||
- OSTree commit failures
|
||||
|
||||
### 12. Transaction Completion
|
||||
|
||||
**Steps**:
|
||||
1. **Success Path**:
|
||||
- Mark transaction as successful
|
||||
- Emit completion signals
|
||||
- Clean up temporary files
|
||||
- Update system state
|
||||
|
||||
2. **Failure Path**:
|
||||
- Rollback to previous state
|
||||
- Clean up partial changes
|
||||
- Emit error signals
|
||||
- Provide error details
|
||||
|
||||
3. **Reboot Handling**: If `--reboot` specified
|
||||
```cpp
|
||||
if (opt_reboot) {
|
||||
// Schedule reboot after transaction completion
|
||||
rpmostree_sysroot_deploy_tree (sysroot, osname, new_commit,
|
||||
OSTREE_SYSROOT_DEPLOY_FLAGS_REBOOT, ...);
|
||||
}
|
||||
```
|
||||
|
||||
## Final Steps
|
||||
|
||||
### 13. System State Update
|
||||
|
||||
**Steps**:
|
||||
1. **Deployment Activation**: Activate new deployment
|
||||
- Update bootloader entries
|
||||
- Set new deployment as default
|
||||
- Preserve rollback deployment
|
||||
|
||||
2. **Cache Updates**: Update package metadata cache
|
||||
- Refresh repository metadata
|
||||
- Update package lists
|
||||
- Cache dependency information
|
||||
|
||||
3. **Cleanup**: Remove temporary files and caches
|
||||
- Clean downloaded RPMs
|
||||
- Remove temporary directories
|
||||
- Update system journal
|
||||
|
||||
### 14. User Feedback
|
||||
|
||||
**Steps**:
|
||||
1. **Status Display**: Show final status
|
||||
```bash
|
||||
# Example output
|
||||
Checking out packages...done
|
||||
Running pre scripts...done
|
||||
Running post scripts...done
|
||||
Writing rpmdb...done
|
||||
Writing OSTree commit...done
|
||||
```
|
||||
|
||||
2. **Deployment Information**: Display deployment details
|
||||
- New deployment checksum
|
||||
- Package changes summary
|
||||
- Reboot requirement (if applicable)
|
||||
|
||||
3. **Next Steps**: Provide guidance for user
|
||||
- Reboot instructions if needed
|
||||
- Package verification commands
|
||||
- Rollback instructions
|
||||
|
||||
## Key Architectural Insights
|
||||
|
||||
### 1. **Client-Daemon Architecture**
|
||||
- CLI client handles user interaction and D-Bus communication
|
||||
- Daemon (rpm-ostreed) handles all privileged operations
|
||||
- Clear separation of concerns and security boundaries
|
||||
|
||||
### 2. **Transaction-Based Design**
|
||||
- All operations wrapped in transactions
|
||||
- Atomic operations with rollback capability
|
||||
- Progress monitoring and cancellation support
|
||||
|
||||
### 3. **Layered Filesystem Model**
|
||||
- Base OSTree commit remains immutable
|
||||
- Package changes applied as overlays
|
||||
- Clear separation between system and user packages
|
||||
|
||||
### 4. **Dependency Management**
|
||||
- Full dependency resolution via libdnf
|
||||
- Handles complex dependency graphs
|
||||
- Conflict resolution and alternatives
|
||||
|
||||
### 5. **Error Handling and Recovery**
|
||||
- Comprehensive error handling at each stage
|
||||
- Automatic rollback on failures
|
||||
- Detailed error reporting and logging
|
||||
|
||||
This analysis reveals the sophisticated architecture of rpm-ostree, which combines the atomic deployment model of OSTree with the powerful package management capabilities of DNF, all orchestrated through a robust client-daemon architecture with comprehensive transaction management.
|
||||
Loading…
Add table
Add a link
Reference in a new issue