bootc-docs/upgrade/technical-reference.md
robojerk 526f1c1afd Initial commit: Comprehensive Debian bootc documentation
- Complete documentation for all bootc commands and subcommands
- Debian-specific adaptations and workarounds
- Manual installation methods to bypass bootc reliability issues
- Technical guides with Rust source code analysis
- Flowcharts and external command references
- Hidden command documentation (bootc internals, state, etc.)
- Composefs integration analysis
- Base image creation guides (with and without bootc binary)
- Management scripts and automation
- Comprehensive troubleshooting and examples
2025-09-15 14:02:28 -07:00

422 lines
11 KiB
Markdown

# bootc upgrade - Technical Reference
## Architecture Overview
The bootc upgrade system is built on OSTree's A/B deployment model, providing transactional updates with rollback capabilities. The system integrates with container registries to pull updates and stages them for application at the next boot.
## Core Components
### 1. Upgrade Command Structure
```rust
// From cli.rs:64-89
pub(crate) struct UpgradeOpts {
pub(crate) quiet: bool, // Suppress progress output
pub(crate) check: bool, // Check-only mode
pub(crate) apply: bool, // Apply and reboot
pub(crate) soft_reboot: Option<SoftRebootMode>, // Soft reboot behavior
pub(crate) progress: ProgressOptions, // Progress reporting
}
```
**Purpose**: Command-line interface configuration
**Features**: Mutually exclusive options, progress control, soft reboot support
### 2. Upgrade Implementation
```rust
// From cli.rs:860-969
async fn upgrade(opts: UpgradeOpts) -> Result<()> {
let sysroot = &get_storage().await?;
let ostree = sysroot.get_ostree()?;
let repo = &ostree.repo();
let (booted_deployment, _deployments, host) = crate::status::get_status_require_booted(ostree)?;
let imgref = host.spec.image.as_ref();
let prog: ProgressWriter = opts.progress.try_into()?;
// ... upgrade logic
}
```
**Process Flow**:
1. **System Validation**: Check system status and compatibility
2. **Image Resolution**: Determine source image reference
3. **Update Check**: Verify if updates are available
4. **Download/Stage**: Pull and stage updates
5. **Application**: Apply updates if requested
## Upgrade Modes
### 1. Check Mode (`--check`)
```rust
// From cli.rs:894-915
if opts.check {
let imgref = imgref.clone().into();
let mut imp = crate::deploy::new_importer(repo, &imgref).await?;
match imp.prepare().await? {
PrepareResult::AlreadyPresent(_) => {
println!("No changes in: {imgref:#}");
}
PrepareResult::Ready(r) => {
crate::deploy::check_bootc_label(&r.config);
println!("Update available for: {imgref:#}");
if let Some(version) = r.version() {
println!(" Version: {version}");
}
println!(" Digest: {}", r.manifest_digest);
changed = true;
// ... diff printing
}
}
}
```
**Purpose**: Check for updates without downloading
**Benefits**: Fast execution, minimal bandwidth usage
**Output**: Update availability, version info, digest comparison
### 2. Download Mode (default)
```rust
// From cli.rs:916-949
let fetched = crate::deploy::pull(repo, imgref, None, opts.quiet, prog.clone()).await?;
let staged_digest = staged_image.map(|s| s.digest().expect("valid digest in status"));
let fetched_digest = &fetched.manifest_digest;
let staged_unchanged = staged_digest
.as_ref()
.map(|d| d == fetched_digest)
.unwrap_or_default();
let booted_unchanged = booted_image
.as_ref()
.map(|img| &img.manifest_digest == fetched_digest)
.unwrap_or_default();
if staged_unchanged {
println!("Staged update present, not changed.");
handle_staged_soft_reboot(ostree, opts.soft_reboot, &host)?;
if opts.apply {
crate::reboot::reboot()?;
}
} else if booted_unchanged {
println!("No update available.")
} else {
let osname = booted_deployment.osname();
crate::deploy::stage(sysroot, &osname, &fetched, &spec, prog.clone()).await?;
changed = true;
// ... diff printing
}
```
**Purpose**: Download and stage updates
**Process**: Registry pull → OSTree import → Staging → Status update
**Features**: Duplicate detection, progress reporting, diff display
### 3. Apply Mode (`--apply`)
```rust
// From cli.rs:951-968
if changed {
sysroot.update_mtime()?;
if opts.soft_reboot.is_some() {
let updated_host = crate::status::get_status(ostree, Some(&booted_deployment))?.1;
handle_staged_soft_reboot(ostree, opts.soft_reboot, &updated_host)?;
}
if opts.apply {
crate::reboot::reboot()?;
}
} else {
tracing::debug!("No changes");
}
```
**Purpose**: Apply staged updates and reboot
**Process**: Update system status → Handle soft reboot → Reboot system
**Features**: Soft reboot support, automatic reboot, status updates
## Soft Reboot System
### 1. Soft Reboot Modes
```rust
// From cli.rs:81-85
#[clap(long = "soft-reboot", conflicts_with = "check")]
pub(crate) soft_reboot: Option<SoftRebootMode>,
```
**Modes**:
- `required`: Fail if soft reboot unavailable
- `auto`: Use soft reboot if available, fallback to regular reboot
### 2. Soft Reboot Handling
```rust
// From cli.rs:954-959
if opts.soft_reboot.is_some() {
let updated_host = crate::status::get_status(ostree, Some(&booted_deployment))?.1;
handle_staged_soft_reboot(ostree, opts.soft_reboot, &updated_host)?;
}
```
**Purpose**: Configure soft reboot behavior
**Process**: Check availability → Configure if supported → Fallback if needed
## Registry Integration
### 1. Image Reference Resolution
```rust
// From cli.rs:865-889
let imgref = host.spec.image.as_ref();
let booted_image = host
.status
.booted
.as_ref()
.map(|b| b.query_image(repo))
.transpose()?
.flatten();
let imgref = imgref.ok_or_else(|| anyhow::anyhow!("No image source specified"))?;
```
**Purpose**: Determine source image for updates
**Process**: Get from host spec → Validate availability → Use for upgrade
### 2. Container Registry Pull
```rust
// From cli.rs:917
let fetched = crate::deploy::pull(repo, imgref, None, opts.quiet, prog.clone()).await?;
```
**Purpose**: Download container image from registry
**Process**: Registry authentication → Layer download → OSTree conversion
**Features**: Progress reporting, error handling, signature verification
## OSTree Integration
### 1. Deployment Management
```rust
// From cli.rs:864
let (booted_deployment, _deployments, host) = crate::status::get_status_require_booted(ostree)?;
```
**Purpose**: Get current system state
**Process**: Query OSTree → Get booted deployment → Get host configuration
### 2. Staging Process
```rust
// From cli.rs:940
crate::deploy::stage(sysroot, &osname, &fetched, &spec, prog.clone()).await?;
```
**Purpose**: Stage updates for next boot
**Process**: Create new deployment → Configure bootloader → Update status
**Features**: Atomic staging, rollback capability, state preservation
## Status Management
### 1. System Status Query
```rust
// From cli.rs:864
let (booted_deployment, _deployments, host) = crate::status::get_status_require_booted(ostree)?;
```
**Purpose**: Get current system state
**Returns**: Booted deployment, all deployments, host configuration
### 2. Status Updates
```rust
// From cli.rs:952
sysroot.update_mtime()?;
```
**Purpose**: Update system modification time
**Process**: Update filesystem timestamp → Trigger status refresh
## Error Handling
### 1. Compatibility Checks
```rust
// From cli.rs:869-879
if imgref.is_none() {
let booted_incompatible = host.status.booted.as_ref().is_some_and(|b| b.incompatible);
let staged_incompatible = host.status.staged.as_ref().is_some_and(|b| b.incompatible);
if booted_incompatible || staged_incompatible {
return Err(anyhow::anyhow!(
"Deployment contains local rpm-ostree modifications; cannot upgrade via bootc. You can run `rpm-ostree reset` to undo the modifications."
));
}
}
```
**Purpose**: Check system compatibility
**Checks**: Local modifications, incompatible deployments
**Error**: Prevents upgrade on incompatible systems
### 2. Update Validation
```rust
// From cli.rs:902
crate::deploy::check_bootc_label(&r.config);
```
**Purpose**: Validate container image compatibility
**Checks**: bootc labels, image configuration
**Error**: Prevents upgrade of incompatible images
## Progress Reporting
### 1. Progress Writer
```rust
// From cli.rs:866
let prog: ProgressWriter = opts.progress.try_into()?;
```
**Purpose**: Handle progress output
**Features**: Quiet mode support, progress bars, status updates
### 2. Progress Options
```rust
// From cli.rs:87-88
#[clap(flatten)]
pub(crate) progress: ProgressOptions,
```
**Purpose**: Configure progress display
**Options**: Quiet mode, progress bars, status updates
## Diff and Comparison
### 1. Manifest Comparison
```rust
// From cli.rs:910-913
if let Some(previous_image) = booted_image.as_ref() {
let diff = ostree_container::ManifestDiff::new(&previous_image.manifest, &r.manifest);
diff.print();
}
```
**Purpose**: Show differences between images
**Process**: Compare manifests → Generate diff → Display changes
**Features**: Layer changes, configuration differences, size changes
### 2. Update Information
```rust
// From cli.rs:903-908
println!("Update available for: {imgref:#}");
if let Some(version) = r.version() {
println!(" Version: {version}");
}
println!(" Digest: {}", r.manifest_digest);
```
**Purpose**: Display update information
**Information**: Image reference, version, digest, changes
## System Integration
### 1. Storage Management
```rust
// From cli.rs:861
let sysroot = &get_storage().await?;
```
**Purpose**: Get system storage interface
**Features**: OSTree integration, filesystem management
### 2. Reboot Integration
```rust
// From cli.rs:962
crate::reboot::reboot()?;
```
**Purpose**: Reboot system after update
**Process**: Trigger system reboot → Apply staged updates
**Features**: Soft reboot support, reboot coordination
## Performance Optimizations
### 1. Duplicate Detection
```rust
// From cli.rs:922-929
let staged_unchanged = staged_digest
.as_ref()
.map(|d| d == fetched_digest)
.unwrap_or_default();
let booted_unchanged = booted_image
.as_ref()
.map(|img| &img.manifest_digest == fetched_digest)
.unwrap_or_default();
```
**Purpose**: Avoid unnecessary downloads
**Process**: Compare digests → Skip if unchanged
**Benefits**: Reduced bandwidth, faster execution
### 2. Incremental Updates
```rust
// From cli.rs:917
let fetched = crate::deploy::pull(repo, imgref, None, opts.quiet, prog.clone()).await?;
```
**Purpose**: Download only changed layers
**Process**: Registry comparison → Layer download → OSTree import
**Benefits**: Reduced bandwidth, faster updates
## Security Features
### 1. Signature Verification
```rust
// From cli.rs:917
let fetched = crate::deploy::pull(repo, imgref, None, opts.quiet, prog.clone()).await?;
```
**Purpose**: Verify image signatures
**Process**: Registry authentication → Signature verification → Image validation
**Features**: Cryptographic verification, trust validation
### 2. Image Validation
```rust
// From cli.rs:902
crate::deploy::check_bootc_label(&r.config);
```
**Purpose**: Validate image compatibility
**Process**: Check bootc labels → Verify configuration → Validate compatibility
**Features**: Label verification, configuration validation
## Future Enhancements
### 1. Planned Features
- **Userspace Restart**: For kernel-unchanged updates
- **Delta Updates**: More efficient layer downloads
- **Rollback Automation**: Automatic rollback on failure
- **Update Scheduling**: Time-based update application
### 2. Integration Improvements
- **API Support**: REST API for update management
- **Webhook Integration**: Event notifications
- **Metrics Collection**: Update performance metrics
- **Dashboard Integration**: Web-based management
This technical reference provides comprehensive understanding of the bootc upgrade system's architecture, implementation, and integration patterns.