|
| 1 | +// SPDX-FileCopyrightText: Copyright © 2025 Serpent OS Developers |
| 2 | +// |
| 3 | +// SPDX-License-Identifier: MPL-2.0 |
| 4 | + |
| 5 | +use std::path::{Path, PathBuf}; |
| 6 | + |
| 7 | +use disks::BlockDevice; |
| 8 | +use partitioning::{blkpg, loopback, sparsefile, writer::DiskWriter}; |
| 9 | +use provisioning::{Parser, Provisioner, StrategyDefinition}; |
| 10 | + |
| 11 | +/// Loads provisioning strategies from a configuration file |
| 12 | +/// |
| 13 | +/// # Arguments |
| 14 | +/// * `path` - Path to the provisioning configuration file |
| 15 | +/// |
| 16 | +/// # Returns |
| 17 | +/// * `Result<Vec<StrategyDefinition>>` - Vector of loaded strategy definitions |
| 18 | +fn load_provisioning(path: impl Into<PathBuf>) -> Result<Vec<StrategyDefinition>, Box<dyn std::error::Error>> { |
| 19 | + let p = path.into(); |
| 20 | + let parser = Parser::new_for_path(p)?; |
| 21 | + Ok(parser.strategies) |
| 22 | +} |
| 23 | + |
| 24 | +/// Applies partitioning strategies to a block device |
| 25 | +/// |
| 26 | +/// # Arguments |
| 27 | +/// * `whence` - Path to the block device to partition |
| 28 | +/// |
| 29 | +/// # Returns |
| 30 | +/// * `Result<()>` - Success or error status |
| 31 | +fn apply_partitioning(whence: &Path) -> Result<(), Box<dyn std::error::Error>> { |
| 32 | + // Initialize provisioner and load strategies |
| 33 | + let mut prov = Provisioner::new(); |
| 34 | + for strategy in load_provisioning("crates/provisioning/tests/use_whole_disk.kdl")? { |
| 35 | + prov.add_strategy(strategy); |
| 36 | + } |
| 37 | + |
| 38 | + // Set up block device |
| 39 | + let device = disks::loopback::Device::from_device_path(whence).ok_or("Not a loop device")?; |
| 40 | + let blk = BlockDevice::loopback_device(device); |
| 41 | + prov.push_device(blk); |
| 42 | + |
| 43 | + // Generate and validate partitioning plans |
| 44 | + let plans = prov.plan(); |
| 45 | + for plan in &plans { |
| 46 | + eprintln!("Plan: {}", plan.strategy.name); |
| 47 | + } |
| 48 | + let plan = plans.first().ok_or("No plans")?; |
| 49 | + |
| 50 | + // Apply partitioning changes |
| 51 | + for (disk, device_plan) in plan.device_assignments.iter() { |
| 52 | + eprintln!("strategy for {} is now: {}", disk, device_plan.strategy.describe()); |
| 53 | + eprintln!("After: {}", device_plan.planner.describe_changes()); |
| 54 | + |
| 55 | + let disk_writer = DiskWriter::new(device_plan.device, &device_plan.planner); |
| 56 | + disk_writer.simulate()?; |
| 57 | + eprintln!("Simulation passed"); |
| 58 | + disk_writer.write()?; |
| 59 | + } |
| 60 | + |
| 61 | + Ok(()) |
| 62 | +} |
| 63 | + |
| 64 | +/// Main entry point - creates and partitions a loopback device |
| 65 | +fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 66 | + // Create sparse file and attach loopback device |
| 67 | + sparsefile::create("lesparse.img", 32 * 1024 * 1024 * 1024)?; |
| 68 | + let l = loopback::LoopDevice::create()?; |
| 69 | + l.attach("lesparse.img")?; |
| 70 | + |
| 71 | + eprintln!("Loopback device: {:?}", &l.path); |
| 72 | + |
| 73 | + // Apply partitioning and handle errors |
| 74 | + let whence = PathBuf::from(&l.path); |
| 75 | + if let Err(e) = apply_partitioning(&whence) { |
| 76 | + eprintln!("Error applying partitioning: {}", e); |
| 77 | + } |
| 78 | + |
| 79 | + // Sync partition table changes |
| 80 | + blkpg::sync_gpt_partitions(whence)?; |
| 81 | + |
| 82 | + // Clean up loopback device |
| 83 | + l.detach()?; |
| 84 | + |
| 85 | + Ok(()) |
| 86 | +} |
0 commit comments