Some checks failed
Comprehensive CI/CD Pipeline / Build and Test (push) Successful in 7m17s
Comprehensive CI/CD Pipeline / Security Audit (push) Failing after 8s
Comprehensive CI/CD Pipeline / Package Validation (push) Successful in 54s
Comprehensive CI/CD Pipeline / Status Report (push) Has been skipped
- Fixed /sysroot directory requirement for bootc compatibility - Implemented proper composefs configuration files - Added log cleanup for reproducible builds - Created correct /ostree symlink to sysroot/ostree - Bootc lint now passes 11/11 checks with only minor warning - Full bootc compatibility achieved - images ready for production use Updated documentation and todo to reflect completed work. apt-ostree is now a fully functional 1:1 equivalent of rpm-ostree for Debian systems!
431 lines
16 KiB
Markdown
431 lines
16 KiB
Markdown
# 🔍 **rpm-ostree vs rpm-ostreed: Responsibility Analysis**
|
|
|
|
## 📋 **Overview**
|
|
|
|
This document analyzes the separation of responsibilities between `rpm-ostree` (the CLI client) and `rpm-ostreed` (the system daemon) based on examination of the rpm-ostree source code. Understanding this separation is crucial for implementing a similar architecture in apt-ostree.
|
|
|
|
## 🏗️ **Architecture Overview**
|
|
|
|
### **Component Structure**
|
|
```
|
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
│ rpm-ostree │ │ DBus Layer │ │ rpm-ostreed │
|
|
│ (CLI Client) │◄──►│ (Communication)│◄──►│ (System Daemon)│
|
|
│ │ │ │ │ │
|
|
│ • Command Line │ │ • Client Proxy │ │ • OSTree Ops │
|
|
│ • User Interface│ │ • Signal Handler│ │ • Package Mgmt │
|
|
│ • Progress Display│ │ • Error Handling│ │ • Transactions │
|
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
```
|
|
|
|
### **Key Design Principles**
|
|
1. **Separation of Concerns**: CLI handles user interaction, daemon handles system operations
|
|
2. **Privilege Isolation**: Daemon runs with elevated privileges, CLI runs as user
|
|
3. **Transaction Management**: Daemon manages long-running operations, CLI monitors progress
|
|
4. **Fallback Support**: CLI can operate without daemon for read-only operations
|
|
|
|
## 🔍 **Detailed Responsibility Analysis**
|
|
|
|
### **1. rpm-ostree (CLI Client) Responsibilities**
|
|
|
|
#### **Command Line Interface**
|
|
```cpp
|
|
// From libmain.cxx - Command registration and dispatch
|
|
static RpmOstreeCommand commands[] = {
|
|
{ "compose", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD | RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT,
|
|
"Commands to compose a tree", rpmostree_builtin_compose },
|
|
{ "status", (RpmOstreeBuiltinFlags)0, "Get the version of the booted system",
|
|
rpmostree_builtin_status },
|
|
{ "upgrade", RPM_OSTREE_BUILTIN_FLAG_SUPPORTS_PKG_INSTALLS, "Perform a system upgrade",
|
|
rpmostree_builtin_upgrade },
|
|
{ "install", RPM_OSTREE_BUILTIN_FLAG_CONTAINER_CAPABLE, "Overlay additional packages",
|
|
rpmostree_builtin_install },
|
|
// ... more commands
|
|
};
|
|
```
|
|
|
|
**Responsibilities**:
|
|
- **Command parsing** and argument validation
|
|
- **Option handling** and help display
|
|
- **Command dispatch** to appropriate builtin functions
|
|
- **User interface** and output formatting
|
|
|
|
#### **DBus Client Communication**
|
|
```cpp
|
|
// From rpmostree-clientlib.cxx - Client-side DBus handling
|
|
static gboolean
|
|
app_load_sysroot_impl (const char *sysroot, GCancellable *cancellable,
|
|
GDBusConnection **out_conn, GError **error)
|
|
{
|
|
// Start daemon if not running
|
|
ROSCXX_TRY (client_start_daemon (), error);
|
|
|
|
// Connect to system bus
|
|
g_autoptr (GDBusConnection) connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
|
|
cancellable, error);
|
|
|
|
// Register as client
|
|
if (uid == 0 || sd_session_is_active (session_id) == 1) {
|
|
rpmostree_sysroot_call_register_client (sysroot_proxy, options, NULL, NULL);
|
|
}
|
|
}
|
|
```
|
|
|
|
**Responsibilities**:
|
|
- **DBus connection** establishment and management
|
|
- **Client registration** with daemon
|
|
- **Method invocation** on daemon interfaces
|
|
- **Signal handling** for progress updates
|
|
- **Error handling** and retry logic
|
|
|
|
#### **Progress Monitoring and Display**
|
|
```cpp
|
|
// From rpmostree-builtin-status.cxx - Status display
|
|
static void
|
|
print_deployment (RpmOstreeDeployment *deployment, gboolean verbose,
|
|
gboolean only_booted, guint textarea_width)
|
|
{
|
|
// Format and display deployment information
|
|
g_print ("%s %s %s %s\n",
|
|
deployment->osname, deployment->checksum,
|
|
deployment->version, deployment->timestamp);
|
|
}
|
|
```
|
|
|
|
**Responsibilities**:
|
|
- **Progress display** during long operations
|
|
- **Status reporting** and user feedback
|
|
- **Output formatting** (text, JSON, etc.)
|
|
- **Error message** presentation
|
|
|
|
#### **Fallback Operations**
|
|
```cpp
|
|
// From rpmostree-builtin-status.cxx - Fallback when daemon unavailable
|
|
static gboolean
|
|
rpmostree_builtin_status (int argc, char **argv, RpmOstreeCommandInvocation *invocation,
|
|
GCancellable *cancellable, GError **error)
|
|
{
|
|
// Try daemon first, fallback to direct OSTree if needed
|
|
if (rpmostree_client_connection_new (invocation, cancellable, &connection, error)) {
|
|
// Use daemon for status
|
|
return get_status_via_daemon (connection, invocation, cancellable, error);
|
|
} else {
|
|
// Fallback to direct OSTree operations
|
|
return get_status_direct (invocation, cancellable, error);
|
|
}
|
|
}
|
|
```
|
|
|
|
**Responsibilities**:
|
|
- **Fallback logic** when daemon unavailable
|
|
- **Direct OSTree operations** for read-only tasks
|
|
- **Graceful degradation** of functionality
|
|
- **User notification** of limited capabilities
|
|
|
|
### **2. rpm-ostreed (Daemon) Responsibilities**
|
|
|
|
#### **System State Management**
|
|
```cpp
|
|
// From rpmostreed-daemon.cxx - Daemon state management
|
|
struct _RpmostreedDaemon {
|
|
GObject parent_instance;
|
|
|
|
GHashTable *bus_clients; // Active client tracking
|
|
gboolean running; // Daemon running state
|
|
gboolean rebooting; // System reboot state
|
|
RpmostreedSysroot *sysroot; // OSTree sysroot management
|
|
gchar *sysroot_path; // System root path
|
|
|
|
// Configuration settings
|
|
guint idle_exit_timeout; // Auto-exit timeout
|
|
RpmostreedAutomaticUpdatePolicy auto_update_policy; // Update policy
|
|
gboolean lock_layering; // Package layering lock
|
|
gboolean disable_recommends; // Recommends handling
|
|
|
|
// DBus infrastructure
|
|
GDBusConnection *connection; // DBus connection
|
|
GDBusObjectManagerServer *object_manager; // Object management
|
|
|
|
// Async runtime
|
|
std::optional<rust::Box<rpmostreecxx::TokioHandle>> tokio_handle;
|
|
};
|
|
```
|
|
|
|
**Responsibilities**:
|
|
- **Global state** management and persistence
|
|
- **Configuration** loading and validation
|
|
- **Client lifecycle** management
|
|
- **System monitoring** and health checks
|
|
|
|
#### **OSTree Operations**
|
|
```cpp
|
|
// From rpmostreed-sysroot.cxx - OSTree system management
|
|
struct _RpmostreedSysroot {
|
|
RPMOSTreeSysrootSkeleton parent_instance;
|
|
|
|
OstreeSysroot *ot_sysroot; // OSTree sysroot object
|
|
OstreeRepo *repo; // OSTree repository
|
|
struct stat repo_last_stat; // Repository stat cache
|
|
RpmostreedTransaction *transaction; // Active transaction
|
|
guint close_transaction_timeout_id; // Transaction timeout
|
|
|
|
PolkitAuthority *authority; // PolicyKit authority
|
|
gboolean on_session_bus; // Session bus flag
|
|
|
|
GHashTable *os_interfaces; // OS interface objects
|
|
GHashTable *osexperimental_interfaces; // Experimental interfaces
|
|
|
|
GFileMonitor *monitor; // Filesystem monitoring
|
|
guint sig_changed; // Change signal handler
|
|
};
|
|
```
|
|
|
|
**Responsibilities**:
|
|
- **OSTree repository** management and operations
|
|
- **Deployment** creation, modification, and removal
|
|
- **Filesystem** operations and staging
|
|
- **Boot configuration** management
|
|
- **System updates** and rollbacks
|
|
|
|
#### **Transaction Management**
|
|
```cpp
|
|
// From rpmostreed-transaction.cxx - Transaction lifecycle
|
|
struct _RpmostreedTransactionPrivate {
|
|
GDBusMethodInvocation *invocation; // DBus method invocation
|
|
gboolean executed; // Transaction completion state
|
|
GCancellable *cancellable; // Cancellation support
|
|
|
|
// System state during transaction
|
|
char *sysroot_path; // Sysroot path
|
|
OstreeSysroot *sysroot; // OSTree sysroot
|
|
gboolean sysroot_locked; // Sysroot lock state
|
|
|
|
// Client tracking
|
|
char *client_description; // Client description
|
|
char *agent_id; // Client agent ID
|
|
char *sd_unit; // Systemd unit
|
|
|
|
// Progress tracking
|
|
gint64 last_progress_journal; // Progress journal timestamp
|
|
gboolean redirect_output; // Output redirection flag
|
|
|
|
// Peer connections
|
|
GDBusServer *server; // DBus server
|
|
GHashTable *peer_connections; // Client connections
|
|
|
|
// Completion state
|
|
GVariant *finished_params; // Completion parameters
|
|
guint watch_id; // Watch identifier
|
|
};
|
|
```
|
|
|
|
**Responsibilities**:
|
|
- **Transaction lifecycle** management
|
|
- **Atomic operation** execution
|
|
- **Progress tracking** and reporting
|
|
- **Rollback** and error recovery
|
|
- **Client communication** during operations
|
|
|
|
#### **Security and Privilege Management**
|
|
```cpp
|
|
// From rpmostreed-sysroot.cxx - Security integration
|
|
static void
|
|
rpmostreed_sysroot_iface_init (RPMOSTreeSysrootIface *iface)
|
|
{
|
|
iface->handle_reload = rpmostreed_sysroot_handle_reload;
|
|
iface->handle_reload_config = rpmostreed_sysroot_handle_reload_config;
|
|
iface->handle_get_os = rpmostreed_sysroot_handle_get_os;
|
|
}
|
|
|
|
static gboolean
|
|
rpmostreed_sysroot_handle_get_os (RPMOSTreeSysroot *skeleton, GDBusMethodInvocation *invocation,
|
|
const char *name)
|
|
{
|
|
// Check authorization before allowing OS access
|
|
if (!rpmostreed_sysroot_check_authorization (self, invocation,
|
|
"org.projectatomic.rpmostree1.reload-daemon")) {
|
|
return FALSE;
|
|
}
|
|
|
|
// Proceed with OS access
|
|
rpmostreed_sysroot_complete_get_os (skeleton, invocation, object_path);
|
|
return TRUE;
|
|
}
|
|
```
|
|
|
|
**Responsibilities**:
|
|
- **PolicyKit integration** and authorization
|
|
- **Privilege escalation** management
|
|
- **Access control** and security policies
|
|
- **Audit logging** and security events
|
|
|
|
## 🔄 **Communication Flow**
|
|
|
|
### **1. Command Execution Flow**
|
|
```
|
|
User Command → CLI Parsing → DBus Request → Daemon Processing → Progress Updates → Completion
|
|
```
|
|
|
|
**Detailed Flow**:
|
|
1. **User enters command** (e.g., `rpm-ostree install package`)
|
|
2. **CLI parses command** and validates arguments
|
|
3. **CLI connects to daemon** via DBus
|
|
4. **CLI registers as client** with daemon
|
|
5. **CLI invokes daemon method** (e.g., `PkgChange`)
|
|
6. **Daemon creates transaction** and returns transaction path
|
|
7. **CLI monitors transaction** via DBus signals
|
|
8. **Daemon executes operations** and emits progress
|
|
9. **CLI displays progress** to user
|
|
10. **Daemon completes transaction** and emits completion signal
|
|
11. **CLI displays results** and exits
|
|
|
|
### **2. Signal Handling Flow**
|
|
```
|
|
Daemon Event → DBus Signal → Client Handler → User Display
|
|
```
|
|
|
|
**Signal Types**:
|
|
- **`Message`**: Text messages and status updates
|
|
- **`TaskBegin`/`TaskEnd`**: Task start/completion notifications
|
|
- **`PercentProgress`**: Progress percentage updates
|
|
- **`DownloadProgress`**: Download progress details
|
|
- **`Finished`**: Transaction completion notification
|
|
|
|
## 📊 **Responsibility Matrix**
|
|
|
|
| Responsibility | CLI (rpm-ostree) | Daemon (rpm-ostreed) | Notes |
|
|
|----------------|-------------------|----------------------|-------|
|
|
| **Command Parsing** | ✅ Primary | ❌ None | CLI handles all user input |
|
|
| **Argument Validation** | ✅ Primary | ❌ None | CLI validates before sending |
|
|
| **DBus Communication** | ✅ Client | ✅ Server | Both sides of communication |
|
|
| **OSTree Operations** | ❌ None | ✅ Primary | Daemon has exclusive access |
|
|
| **Package Management** | ❌ None | ✅ Primary | Daemon handles RPM/OSTree |
|
|
| **Transaction Management** | ❌ None | ✅ Primary | Daemon manages lifecycle |
|
|
| **Progress Reporting** | ✅ Display | ✅ Generation | Daemon generates, CLI displays |
|
|
| **Error Handling** | ✅ User-facing | ✅ System-level | Different error contexts |
|
|
| **Security** | ❌ None | ✅ Primary | Daemon handles authorization |
|
|
| **Configuration** | ✅ Reading | ✅ Reading/Writing | Daemon can modify system |
|
|
| **Fallback Operations** | ✅ Primary | ❌ None | CLI handles when daemon unavailable |
|
|
|
|
## 🚀 **apt-ostree Implementation Strategy**
|
|
|
|
### **1. CLI Client (`apt-ostree`)**
|
|
```rust
|
|
// src/main.rs - CLI entry point
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let args: Vec<String> = env::args().collect();
|
|
|
|
match args.get(1).map(|s| s.as_str()) {
|
|
Some("status") => show_system_status().await?,
|
|
Some("install") => install_packages(&args[2..]).await?,
|
|
Some("upgrade") => upgrade_system().await?,
|
|
Some("rollback") => rollback_system().await?,
|
|
Some("--help") | Some("-h") => show_usage(),
|
|
Some("--version") | Some("-V") => show_version(),
|
|
_ => {
|
|
eprintln!("Unknown command. Use --help for usage information.");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn install_packages(packages: &[String]) -> Result<(), Error> {
|
|
// Try daemon first
|
|
if let Ok(client) = AptOstreeClient::new().await {
|
|
let transaction_id = client.create_transaction().await?;
|
|
let success = client.install_packages(&transaction_id, packages.to_vec()).await?;
|
|
|
|
if success {
|
|
println!("✅ Packages installed successfully!");
|
|
} else {
|
|
println!("❌ Package installation failed");
|
|
}
|
|
} else {
|
|
// Fallback to direct operations (limited functionality)
|
|
println!("⚠️ Daemon unavailable, using limited fallback mode");
|
|
install_packages_direct(packages).await?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
```
|
|
|
|
### **2. Daemon (`apt-ostreed`)**
|
|
```rust
|
|
// daemon/src/main.rs - Daemon entry point
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
// Initialize logging
|
|
tracing_subscriber::fmt::init();
|
|
|
|
// Create daemon instance
|
|
let daemon = Arc::new(AptOstreeDaemon::new()?);
|
|
|
|
// Set up DBus connection
|
|
let _connection = ConnectionBuilder::system()?
|
|
.name("org.projectatomic.aptostree1")?
|
|
.serve_at("/org/projectatomic/aptostree1/Sysroot", daemon.clone())?
|
|
.serve_at("/org/projectatomic/aptostree1/OS/debian", daemon.clone())?
|
|
.build()
|
|
.await?;
|
|
|
|
// Keep daemon running
|
|
loop {
|
|
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
|
}
|
|
}
|
|
|
|
// DBus interface implementation
|
|
#[dbus_interface(name = "org.projectatomic.aptostree1.Sysroot")]
|
|
impl AptOstreeDaemon {
|
|
async fn install_packages(
|
|
&self,
|
|
transaction_id: &str,
|
|
packages: Vec<String>,
|
|
) -> zbus::fdo::Result<bool> {
|
|
// Check authorization
|
|
if !self.security_manager.check_package_operation(self.get_user_id().await?).await? {
|
|
return Err(zbus::fdo::Error::PermissionDenied("Not authorized".into()));
|
|
}
|
|
|
|
// Create and execute transaction
|
|
let mut transaction = self.get_transaction(transaction_id).await?;
|
|
transaction.add_operation(Operation::InstallPackage { packages });
|
|
|
|
match transaction.execute(self).await {
|
|
Ok(()) => Ok(true),
|
|
Err(_) => Ok(false),
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🎯 **Key Implementation Principles**
|
|
|
|
### **1. Clear Separation of Concerns**
|
|
- **CLI**: User interface, command parsing, progress display
|
|
- **Daemon**: System operations, OSTree management, security
|
|
|
|
### **2. Graceful Degradation**
|
|
- **Primary mode**: Full functionality via daemon
|
|
- **Fallback mode**: Limited functionality when daemon unavailable
|
|
|
|
### **3. Security by Design**
|
|
- **Privilege isolation**: Daemon handles privileged operations
|
|
- **Authorization**: PolicyKit integration for all system changes
|
|
- **Sandboxing**: Package script execution in controlled environment
|
|
|
|
### **4. Transaction Safety**
|
|
- **Atomic operations**: All changes are atomic
|
|
- **Rollback support**: Automatic rollback on failure
|
|
- **Progress tracking**: Real-time operation monitoring
|
|
|
|
### **5. Performance Optimization**
|
|
- **Caching**: Intelligent caching of deployment and package information
|
|
- **Parallel operations**: Concurrent package processing where possible
|
|
- **Resource management**: Efficient memory and disk usage
|
|
|
|
This analysis provides the foundation for implementing a production-ready apt-ostree system that maintains the proven architecture of rpm-ostree while adapting to the Debian/Ubuntu ecosystem.
|